Java/live-study

백기선라이브스터디 13주차 : I/O

jay Joon 2021. 2. 17. 02:44

목표

자바의 Input과 Ontput에 대해 학습하세요.

학습할 것 (필수)

  • 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O
  • InputStream과 OutputStream
  • Byte와 Character 스트림
  • 표준 스트림 (System.in, System.out, System.err)
  • 파일 읽고 쓰기

Stream

스트림은 단 방향으로 만 데이터가 흘러간다.

이러한 특징 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다.(FIFO 구조)

스트림으로 양방향으로 데이터를 교환하기 위해선 각각의 inputStream , ouptStream을 가지고 있어야 한다.


자바에서의 Stream

자바에서의 Stream 은 바이트 스트림(Byte Stream) , 문자 스트림(Character Stream)으로 나뉜다

또한 스트림은 또 다른 스트림과 서로 연결될 수 있다(테코레이터 패턴).

해당 예제는 다음과 같다.

OutputStreamWriter osw = new OutputStreamWriter(System.out);

System.out 은 바이트 스트림이다.

OutStreamReader은 문자 스트림이다.

즉 System.out 이 읽은 바이너리 데이터를 , 문자로 다루는 OutputStreamWriter 스트림에 연결시키는 것이다.

그럼 이런 행위를 왜 하는 것일까?

다음 코드를 실행 보자.

@Test
void byteStream(){
    System.out.write(3); // 바이트코드 3
    System.out.flush(); // 출력
}

다음 테스트를 실행한다면 콘솔에는 무엇이 찍힐까?

아무것도 찍히지 않거나 3이 아닌 값이 찍힐 것이다.

자 바이트코드 3은 아스키코드표를 보면

이진법 팔진법 십진법 십육진법 약자 설명 한국어설명
000 0011 003 3 03 ETX End of Text 본문 종료

다음과 같다.

따라서 3을 출력하고 싶다면 51 바이트를 입력해줘야 원하는 3이 출력이 된다.

@Test
void byteStream(){
    System.out.write(51); // 바이트코드 51 - > 3
    System.out.flush(); // 출력
}

물론 ' 3'으로 감싸게 되면 바이트코드 51 으로 변환되어 입력값(3) 대로 출력할 수 있다.

하지만 ' ' 으로 감싸는 것은 한 문자씩만 가능하다.

매우 불편하다.

만약 51을 출력하고 싶다면

@Test
void byteStream(){
    System.out.write('5'); 
    System.out.write('1');
    System.out.flush(); // 출력
}

다음과 같이 작성해야 한다.(이렇게 하기 싫으면 아스키코드표 외우고 있어야 함.)

따라서 자바에서는 스트림을 연결시킬 수 있도록 하여 이러한 귀찮은? 코딩을 하지 않게 해 준다.

@Test
void OutputStreamWriter() throws IOException {
    OutputStreamWriter osw = new OutputStreamWriter(System.out);
    rd.write("Hello");
    rd.flush();
}

다른 예)

BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));

코테 준비를 했다면 많이 봤을 것이다. 이처럼 스트림은 연결 이 가능하다.

 


Byte Stream(바이트 스트림)

바이트 스트림의 최상위 클래스는 InuptStream , OutputStream이다.

이 두 클래스는 추상 클래스이며 바이트 스트림을 만들고 싶다면 용도에 따라 이 두 클래스 중 하나를 상속받아야 한다.

img

바이트 스트림 말 그대로 입출력되는 바이트의 바이너리 값을 처리할 수 있다.

-> 스트림에 들어오는 문자, 단순 바이너리 정보이든 상관없이 처리할 수 있다.(문자 스트림은 문자 외 정보가 들어오면 처리 못함)

Character Stream (문자 스트림)

바이트 스트림의 최상위 클래스는 Reader , Writer이다.

이 두 클래스는 추상 클래스이며 문자 스트림을 만들고 싶다면 이 용도에 따라 두 클래스중 하나를 상속받아야 한다.

img

문자가 아닌 단순 바이너리 정보들을 읽거나 쓸려고 하면 문자 스트림은 적합하지 않다.

즉 메모장으로 작성된 텍스트 파일이나 자바 소스파일 같은 문자열로 이루어진 파일만 읽고 쓸 수 있다.

 


표준 스트림 (System.in, System.out, System.err)

System in

-> 키보드로 데이터를 입력받는다 (InputStream)

System.out

->모니터로 데이터를 출력시킴 (Print Stream)

->print() , println(), printf() 등등 외 다른 기능도 있다.

System.err

->에러를 출력장치 (Print Stream)

 

자바의 표준 스트림이 이러한 것이 있다는 것만 알고 넘어가도 될 거 같다

.

자세히 알고 싶다면 docs를 참고하자.

https://docs.oracle.com/javase/8/docs/api/java/lang/System.html


Buffer

자바의 스트림은 버퍼를 사용하는 스트림과 사용하지 않는 스트림이 존재한다.

일단 buffer 란?

데이터를 바로바로 전달하지 않고 중간 저장소에 저장하여

개행 문자가 나타나거나 버퍼의 크기가 가득 차면 중간 저장소에 있는 데이터를 전송시켜주는 기능이다.

이러한 행위를 함으로써 CPU와 외부장치(키보드 , 마우스 등) 간의 속도 차이를 줄여주어 입출력에 대한 속도를 향상해준다.

Image for post


파일 읽고 쓰기

파일 읽기(BufferReader 이용)

public static void main(String[] args) {
    String path = "/code/src/main/java/live_study_13/test.txt";
    File testFile = new File(path);
    try(FileReader fr = new FileReader(testFile);
        BufferedReader br = new BufferedReader(fr)) {
        String line;
        while ((line = br.readLine())!= null){
            System.out.println(line);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

파일 쓰기 (BufferWriter 이용)

public static void main(String[] args) {
    String path = "code/src/main/java/live_study_13/newFile.txt";
    File newFile = new File(path);
    try(FileWriter wr = new FileWriter(newFile);
        BufferedWriter bw = new BufferedWriter(wr)) {
        for (int i = 0; i < 30; i++) {
            bw.write("Hello" +i);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

이 외 Buffer Stream을 이용하지 않고 일반 Buffer가 없는 스트림으로도 파일을 읽고 쓸 수 있다.

하지만 버퍼가 없는 일반 스트림은 파일크기가 커질수록 성능이 안 좋음으로 Buffer 가 있는 스트림을 쓰자.

Buffer Stream종류

input BufferedInputStream(byteStream) BufferedReader(Character Stream)
ouput BufferedOutputStream(byteStream) BufferedWriter(Character Stream)