보조 스트림이란 입출력을 직접 하지 않고 기반 스트림에 추가적인 기능을 부여하는 스트림이다. 사용 방법은 보조스트림 객체를 만들 때 생성자로 기반스트림을 전달해주는 것이다.

보조 스트림은 2개 이상을 사용할 수도 있다. 이 때에는 보조스트림에 생성자로 보조스트림을 전달해주면서 전달된 보조스트림의 생성자에 매개변수로 기반스트림을 주는 식으로 할 수 있다.

보조 스트림의 최상위 클래스는 FilterInputStream과 FilterOutputStream이다. 두 추상클래스의 생성자는 스트림 1개를 매개변수로 전달받는다. 다른 생성자는 지원하지 않는다.

 

1. InputStreamReader / OutputStreamWriter


데이터를 바이트 단위로만 전송할 수 있을 때 한글과 같이 2byte가 필요한 데이터가 있다. 이런 경우에 사용할 수 있는 보조스트림이 InputStreamReader와 OutputStreamWriter이다. 이 두 스트림은 byte단위 데이터를 문자로 변환해주는 보조 스트림이다.

package stream;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class InputStreamReaderTest {

   public static void main(String[] args) {

      try(InputStreamReader isr = new InputStreamReader(new FileInputStream("hello.txt"))){

         int i;
         while((i = isr.read()) != -1) {
            System.out.print((char)i);
         }
      } catch(IOException e) {
         System.out.println(e);
      }
   }

}

실행결과

"자바를자바라"

원래같은 경우라면 FileInputStream은 byte단위로 데이터를 읽기 때문에 한글 문자를 제대로 읽어들일 수 없다. 따라서 보조스트림으로 InputStreamReader 클래스를 사용하였다.

 

OutputStreamWriter의 사용법 역시 이와 비슷하다.

 

2. BufferedInputStream / BufferedOutputStream


BufferedInputStream과 BufferedOutputStream은 버퍼링 기능을 제공하는 보조 스트림이다. 따라서 1byte씩 데이터를 전송하는 스트림보다 더 빨리 입출력을 실행한다. 내부적으로 8192byte 크기의 배열을 가지고 있다.

BufferedInputStream은 생성자의 매개변수로 InputStream 하위클래스를, BufferedOutputStream은 OutputStream 하위클래스를 받는다. 또한 BufferedReader는 Reader, BufferedWriter은 Writer 의 하위 클래스를 생성자의 매개변수로 받는다.

package stream;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class StreamReaderWriterTest {

   public static void main(String[] args) {
      try (FileInputStream fis = new FileInputStream("test.jpg")){
         FileOutputStream fos = new FileOutputStream("copy.jpg");

         long t1 = System.currentTimeMillis(); //시간 측정 시작

         int i;
         while((i = fis.read()) != -1) { //FileInputStream으로 읽어서
            fos.write(i); //FileOutputStream으로 쓰기
         }

         long t2 = System.currentTimeMillis(); //시간 측정 끝

         System.out.println(t2-t1);

      } catch (IOException e) {
         e.printStackTrace();
      }

   }

}

실행결과

5584

byte단위 스트림으로 파일을 읽어 내용을 쓰는 방식으로 복사하였는데 5.584초가 걸린다.

Buffered 스트림 하위 클래스를 사용하여 속도가 개선되는지 확인해보자.

package stream;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class StreamReaderWriterTest {

   public static void main(String[] args) {
      try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("test.jpg"))){
         BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.jpg")) ;

         long t1 = System.currentTimeMillis(); //시간 측정 시작

         int i;
         while((i = bis.read()) != -1) { //BufferedInputStream으로 읽어서
            bos.write(i); //BufferedOutputStream으로 복사
         }

         long t2 = System.currentTimeMillis(); //시간 측정 끝

         System.out.println(t2-t1);

      } catch (IOException e) {
         e.printStackTrace();
      }

   }

}

실행결과

39

0.039초가 걸린다. 아주 심하게 차이가 난다.

'프로그래밍 언어 > Java' 카테고리의 다른 글

(Java) 57 - 객체 직렬화  (0) 2020.05.18
(Java) 55 - Reader와 Writer  (0) 2020.05.18
(Java) 54 - File 입출력  (0) 2020.05.18
(Java) 53 - Scanner 클래스  (0) 2020.05.18
(Java) 52 - Java 입출력  (0) 2020.05.18

+ Recent posts