-
[13주차]IO스터디/[whiteship]JAVA 2021. 2. 20. 19:54
목표
자바의 Input과 Ontput에 대해 학습하세요.
학습할 것 (필수)
- 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
- InputStream과 OutputStream
- Byte와 Character 스트림
- 표준 스트림 (System.in, System.out, System.err)
- 파일 읽고 쓰기
스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
Stream
- 데이터를 운반할 때 사용하는 연결통로, 연속적인 데이터의 흐름을 물(stream)에 비유해서 붙여진 이름이다.
- 자바에선 파일이나 콘솔의 입출력을 직접 다루지 않고 stream이라는 중간 매개를 통해 흐름을 다룬다.
- FIFO(First in First out)구조이다.
- 단반향이기 때문에 입력 스트림과 출력 스트림을 별도로 사용해야 한다.
- 연속된 데이터의 흐름으로 입출력을 진행시 다른 작업을 할 수 없다. -> Blokcing상태
- JAVA 1.4부터 NIO(NEW I/O)로 Non blocking처리가 가능한데 여기선 채널을 이용한다.
- 여기서 말한 stream이란 Java 8에 등장한 stream API가 아니다.
- Stream의 입출력의 기본 단위는 바이트 단위이다.
- 입출력에 사용하는 데이터에 따라, 문자 스트림과 바이트 스트림으로 나뉘게된다.
- 문자 스트림과 바이트 스트림은 모두 바이트 단위로 데이터를 입출력한다는 것은 동일하지만 각기 다른 역활을 수행하는 입출력 스트림이다.
Buffer
- 버퍼란 컴퓨터의 주기억 장치(CPU)와 주변장치 사이(마우스, 키보드, 프린터)에서 데이터를 주고 받을때, 정보를 임시로 저장하는 공간으로써 주기억 장치와 주변장치 사이에서 데이터를 주고받을 때 속도, 시간차로 발생하는 문제점을 해결할 수 있는 고속 임시기억 장치이다. (하드웨어 개념)
- 입출력을 수행할때 보조적 기능을 수행하며 버퍼란 공간에 담아두고 데이터를 전송한다.
- 버퍼없이 데이터가 입력, 출력 할때마다 바로 목적지에 보내게 된다면 입/출력 동안 발생하는 비용이 더 크다 예를들어 모래를 옮긴다는 과정을 생각하면, 손으로 모래를 옮기는 것과 삽으로(버퍼)로 옮기는 것 중 무엇이 효율적인가 생각해볼 수 있다.
Channel
- Channel도 Stream과 마찬가지로 데이터의 흐름이라 말할수 있다 하지만 큰 차이점이 존재하는데, 채널은 양방향 통신이 가능하다는 것이다.
- 채널은 Buffer를 통해서만 데이터 입출력이 가능하다.
- NIO의 입출력 흐름에 사용된다.
※IO vs NIO(new IO)
기존의 IO 방식은 stream을 이용한 입/출력 방식으로 스트림에서 데이터가 입력되거나 출력하기 전까지 blocking(대기) 상태 즉 스레드는 입/출력 작업을 기다려야 하는 상태가 된다. 이런 단점때문에 NIO가 등장했는데 차이점은 다음과 같다.
- NIO는 스레드는 블로킹과 Nonblocking특징 모두를 가진다.
- Nonblocking이란 입출력 작업시 스레드가 블로킹(대기)상태가 되지 않는 것이다.
- NIO는 블로킹은 스레드를 인터럽트함으로써 빠져나올 수 있다.
너무 깊이 가면 해당 포스팅 시간이 오래 걸리기때문에 차후, NIO에대해서 다시 포스팅하겠다.
InputStream과 OutputStream
앞서 말한 stream은 단방향 구조라고 했다, 따라서 입출력시 별도의 출력과 입력을 담당하는 스트림을 사용해야 한다.
- InputStream과 OutputStream는 바이트 기반 스트림의 최상위 추상클래스이다.
InputStream을 상속받는 stream 클래스들
OutputStream을 상속받는 stream 클래스들
[REFERENCES]
www.tcpschool.com/java/java_io_stream
Byte와 Character 스트림
Byte Stream
- Byte 스트림의 경우 1바이트 데이터를 처리한다.
- 바이너리 파일 (그림, 이미지, 파일)등 입/출력에 사용하는 스트림이다.
- Byte 스트림 클래스란 위에 설명한 InputStream과 outputStream와 이를 상속하는 모든 바이트 스트림 클래스를 말한다.
Character Stream
- 문자를 입력, 출력할 때 사용하는 입/출력 스트림이다.
- Character 스트림의 경우 char형, 즉 2바이트씩 처리해 한 문자씩 입, 출력 받을수 있다.
- 문자당(2Byte)인것으로 알고 있음.
- 일반적인 텍스트나 텍스트 파일, JSON, HTML 등 송수신에 사용한다.
[REFERENCES]
www.tcpschool.com/java/java_io_stream
표준 스트림 (System.in, System.out, System.err)
System.in
콘솔로부터 데이터를 입력받는 표준 스트림이다.
System.out
콘솔로 출력하는 표준 스트림 상수로써 우리가 흔히 사용하는 System.out.println()이 있다.
System.err
System.out과 같이 콘솔에 출력하지만 에러를 출력하는 목적에 사용한다.
파일 읽고 쓰기
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { //파일 쓰기 FileWriter file = new FileWriter("/Users/kim/Documents/compileTest/file.txt"); file.write("hello my file"); file.close(); //파일쓰기 FileReader fileReader = new FileReader("/Users/kim/Documents/compileTest/file.txt"); int c; while((c=fileReader.read())!=-1){ System.out.print((char)c); } System.out.println("\n"); System.out.println(System.currentTimeMillis()); } }
FileWriter의 경우, 해당 파일과 연결하여 스트림을 만든후, write메서드로 문자를 입력했다. 만약 생성자로 지정한 경로에 텍스트 파일이 없다면 텍스트 파일을 자동으로 만들어준다. 후에 FileReader를 통해 해당 텍스트 파일을 스트림으로 연결후 콜솔창에서 2바이트(char)으로 한 문자씩 출력했다. 하지만 이렇게하면 위에 설명한 Buffer를 사용하면 어떨까? 한 문자씩 쓰고 읽는 것 보다 훨씬 효율적일 것이다.
보조 스트림은 다음과 같다.스트림이 바이트 혹은 한 문자씩 가지고 오는 것을 버퍼에 저장후 데이터를 입/출력한다스트림의 기능은 없지만, 기능을 향상시키거나 새로운 기능을 추가할수 있다.
bufferedReader를 통한 보조 스트림을 통해 시간을 측정해보았다.사용하지 않았을때
import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); FileReader fileReader = new FileReader("/Users/kim/Documents/compileTest/file.txt"); int c; while((c=fileReader.read())!=-1){ System.out.print((char)c); } long end = System.currentTimeMillis(); System.out.println("\n"); System.out.println((end - start)); } }
16Millis second
버퍼를 사용했을때
import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException { long start = System.currentTimeMillis(); FileReader fileReader = new FileReader("/Users/kim/Documents/compileTest/file.txt"); BufferedReader bufferedReader = new BufferedReader(fileReader); int c; while((c=bufferedReader.read())!=-1){ System.out.print((char)c); } long end = System.currentTimeMillis(); System.out.println("\n"); System.out.println((end - start)); } }
14Millis Second
파일의 내용이 별로 없어서 큰 차이는 안나지만, 대용량일 경우 차이는 분명할 것이다.
[REFERENCES]
'스터디 > [whiteship]JAVA' 카테고리의 다른 글
[9주차]예외처리 (0) 2021.11.23 [6주차]상속 (0) 2021.02.15 [5주차]클래스 (0) 2021.02.12 [4주차]제어문 (0) 2021.01.26 [3주차]자바가 제공하는 다양한 연산자 (0) 2021.01.23