본문 바로가기

언어공부/Java

자바 - 입출력(I/O), 스트림(stream), 바이트 기반 스트림(InputStream, OutputStream), 문자(텍스트) 기반 스트림(Reader, Writer)

자바 입출력(I/O)과 스트림(stream)에 대해서 알아보자.

입출력(I/O)

I/O란 Input과 Output의 약자로 입력과 출력, 간단히 줄여서 입출력이라고 한다. 입출력은 컴퓨터 내부 또는 외부의 장치와 프로그램간의 데이터를 주고 받는 것을 말한다. 예를 들어 키보드로부터 데이터를 입력받는다든가 System.out.println()을 이용해서 화면에 데이터를 출력한다던가 하는것이 가장 기본적인 입출력의 예이다.

 

스트림(stream)

자바에서 입출력을 수행하려면, 즉 어느 한쪽에서 다른쪽으로 데이터를 전달하려면, 두 대상을 연결하고 데이터를 전송할 수 있는 무언가가 필요한데 이것을 스트림(stream)이라고 정의한다. 데이터를 운반하는데 사용되는 연결통로로 볼 수 있다. 

 

스트림은 연속적인 데이터의 흐름을 물에 비유해서 붙여진 이름인데, 물이 한쪽방향으로만 흐르는 것과 같이 스트림은 단방향통신만 가능하기 때문에 하나의 스트림으로 입력과 출력을 동시에 처리할 수 없다.

 

그래서 입력과 출력을 동시에 수행하려면 입력을 위한 입력스트림(input stream)과 출력을 위한 출력스트림(output stream) 총 2개의 스트림이 필요하다. 스트림은 먼저 보낸 데이터를 먼저 받게 되어 있으며 중간에 건너뜀 없이 연속적으로 데이터를 주고 받는다. 큐와 같은 FIFO구조로 되어있다고 생각하면 된다.

 

스트림에는 바이트 기반 스트림(InputStream, OutputStream)과 문자(텍스트) 기반 스트림(Reader, Writer)이 있다.

 

바이트 기반 스트림(InputStream, OutputStream)

스트림은 바이트 단위로 데이터를 전송한다. 바이트 기반은 입출력의 단위가 1 byte라는 뜻이다.  InputStream은 바이트 입력 스트림의 최상위 추상클래스이며, OutputStream은 바이트 출력 스트림의 최상위 추상 클래스이다.

 

InputStream 클래스 메소드

  • int read() : 한 바이트를 읽어 들인다.
  • int read(byte b[]) : 바이트 배열을 읽어 들인다.
  • int read(byte b[], int off, int len) : 바이트 배열의 주어진 위치에 주어진 길이 만큼 읽어 들인다.

여기서 read()의 반환타입이 byte가 아니라 int인 이유는 read()의 반환값의 범위가 0~255와 -1이기 때문.

 

OutputStream 클래스 메소드

  • void close() : 스트림을 닫는다. 스트림을 사용해서 모든 작업을 마치고 난 후에는 close()를 호출해서 반드시 닫아주어야 한다. (메모리를 사용하는 스트림과 표준 입출력 스트림은 닫아 주지 않아도 된다.)
  • void flush() : 출력 스트림이 갖고 있는 버퍼의 내용을 모두 출력 스트림으로 내보내고 비운다. *버퍼가 있는 출력 스트림의 경우에만 의미가 있다.
  • int write(byte[] b, int off, int len) : b 배열의 off위치부터 len 만큼 출력한다.
  • void write(byte[] b) : 바이트 배열로 출력한다.
  • void write(int b) : 한 바이트로 출력한다.

 

보조 스트림

보조스트림은 실제 데이터를 주고 받는 스트림이 아니기 때문에 데이터를 입출력할 수 있는 기능은 없지만, 스트림의 기능을 향상시키거나 새로운 기능을 추가할 수 있다. 그래서 보조 스트림만으로는 입출력을 처리할 수 없고, 스트림을 먼저 생성한 다음에 이를 이용해서 보조 스트림을 생성해야 한다.

 

모든 보조스트림 역시 InputStream과 OutputStream의 자손들이므로 입출력 방법이 같다.

 

문자(텍스트) 기반 스트림(Reader, Writer)

C언어와 달리 Java에서는 한 문자를 의미하는 char형이 1byte가 아니라 2byte이기 때문에 바이트기반의 스트림으로 2 byte의 문자를 처리하는데 어려움이 있다. 이 점을 보완하기 위해서 문자기반의 스트림이 제공된다. 문자데이터를 입출력할 때는 바이트기반 스트림 대신 문자기반 스트림을 사용하는 것이 좋다.

 

Reader는 문자 스트림을 읽어들이기 위한 최상위 추상클래스이며, Writer는 문자 출력 스트림의 최상위 추상 클래스이다.

 

문자기반 스트림의 이름은 바이트기반 스트림의 이름에서 InputStream은 Reader로, OutputStream은 Writer로만 바꾸면 된다. 단 ByteArray가 CharArray로 대응된다.

 

보조스트림 역시  바이트기반 스트림의 이름에서 InputStream은 Reader로, OutputStream은 Writer로만 바꾸면 된다. 바이트기반 보조 스트림과 다르지 않다.