Java :: I/O :: 3. 바이트 기반의 보조 스트림

김병철·2022년 9월 16일
0

Java

목록 보기
10/20

3. 바이트 기반의 보조 스트림

3.1 FilterInputStream / FilterOutputStream

FilterInputStream/FilterOutputStream은 InputStream/OutputStream의 자손이며 모든 보조스트림의 조상이다.

보조스트림 자체로는 입출력을 수행할 수 없기에 기반스트림이 꼭 필요하다.

FilterInputStream/FilterOutputStream자체로는 아무런 일도 하지 않는다.

상속을 통해 원하는 작업을 수행하도록 오버라이딩해야 한다.

public class FilterInputStream extends InputStream {
	protected volatile InputStream in;
	protected FilterInputStream(InputStream in) {
		this.in = in;
    }
    
    public int read() throws IOException {
    	return in.read();
    }
    ...
}

생성자 FilterInputStream(InputStream in)는 'protected'라서 인스턴스를 생성해서 사용할 수 없고, 상속을 통해 오버라이딩 되어야 한다.

상속을 통해 기반스트림에 보조기능을 추가한 보조스트림 클래스는 다음과 같다.

  • FilterInputStream의 자손 :
    -> BufferedInputStream, DataInputStream, PushbackInputStream 등

  • FilterOutputStream의 자손 :
    -> BufferedOutputStream, DataOutputStream, PushbackOutputStream 등


3.2 BufferedInputStream / BufferedOutputStream

BufferedInputStream / BufferedOutputStream은 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림이다.

한 바이트씩 입출력하는 것보다 버퍼(바이트배열)를 이용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용된다.

# BufferedInputStream의 생성자

  • BufferedInputStream(InputStream in, int size) :
    -> 주어진 InputStream 인스턴스를 입력소스(input source)로 하며 지정된 크기(byte단위)의 버퍼를 갖는 BufferedInputStream인스턴스를 생성한다.

  • BufferedInputStream(OutputStream out) :
    -> 주어진 InputStream 인스턴스를 입력소스(input source)로 하며 버퍼의 크기를 지정해주지 않으므로 기본적으로 8192byte 크기의 버퍼를 갖는다.

버퍼의 크기는 입력소스로부터 한 번에 가져올 수 있는 데이터의 크기로 지정하면 좋다.

보통 입력 소스가 파일이면 8192(8K) 정도의 크기로 하는 것이 보통이다.

  • 프로그램에서 버퍼에 저장된 데이터 다 읽기 ->
    그 다음 데이터 읽기 read() ->
    BufferedInputStream이 다시 입력소스로부터 다시 버퍼크기 만큼의 데이터 버퍼에 저장 ->
    반복

# BufferedOutputStream의 생성자와 메서드

  • BufferedOutputStream(OutputStream out, int size)
    -> 주어진 OutputStream 인스턴스를 출력소스 (output source)로 하며 지정된 크기(단위byte)의 버퍼를 갖는 BufferedOutputStream 인스턴스를 생성한다.

  • BufferedOutputStream(OutputStream out)
    -> 주어진 OutputStream 인스턴스를 출력소스(output source)로 하며 버퍼의 크기를 지정해주지 않으므로 기본적으로 8192 byte 크기의 버퍼를 갖는다.

  • flush()
    -> 버퍼의 모든 내용을 출력소스에 출력한 뒤, 버퍼를 비운다.

  • close()
    -> flush()를 호출해서 버퍼의 모든 내용을 출력소스에 출력하고, BufferedOutputStream 인스턴스가 사용하던 모든 자원을 반환한다.

BufferedOutputStream 역시 버퍼를 이용하여 출력소스와 작업한다.

입력과 반대로 write메서드를 이용한 출력이 버퍼에 저장된다.

버퍼가 가득 차면 그 때 버퍼의 모든 내용을 출력소스에 출력한다.

버퍼가 가득 찼을 때만 출력을 하기 때문에, 마지막에 채워진 내용은 버퍼에 남은 채 프로그램이 종료될 수 있다.


# BufferedOutputStream 예제

1부터 9까지 9개의 문자를 쓰는데 버퍼의 크기는 5이다.
전부 출력이 되는지 확인해보자.

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufTest {

	public static void main(String[] args) {
		try {
			FileOutputStream fos = new FileOutputStream("buffTest.txt");
			
			BufferedOutputStream bos = new BufferedOutputStream(fos, 5);
			
			for(int i='1'; i <= '9'; i++) {
				bos.write(i);
			}
			fos.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}
  • 출력 결과 :

1~5까지 출력되고 6, 7, 8, 9가 출력되지 않았다.
버퍼의 크기가 5여서 꽉차지 않았기 때문에 버퍼에 6, 7, 8, 9가 남은 채로 프로그램이 종료되었다.


# BufferedOutputStream 예제 수정

BufferedOutputStream을 닫아주는 close()메소드를 사용하면 버퍼에 남은 것을 모두 출력하고 종료한다.

BufferedOutputStream의 close()는 기반스트림인 FilterOutputStream의 close()를 호출하기 때문에 FilterOutputStream의 close()를 따로 호출하지 않아도 된다.

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufTest {

	public static void main(String[] args) {
		try {
			FileOutputStream fos = new FileOutputStream("buffTest.txt");
			
			BufferedOutputStream bos = new BufferedOutputStream(fos, 5);
			
			for(int i='1'; i <= '9'; i++) {
				bos.write(i);
			}
			bos.close();	// 추가하면 버퍼에 남은 것을 출력하고 종료된다.
			// fos.close();
		} catch(IOException e) {
			e.printStackTrace();
		}
	}
}
  • 출력 결과 :

이처럼 보조스트림을 사용한 경우에 기반스트림의 close()나 flush()를 호출할 필요없이 단순히 보조스트림의 close()만 호출하면 된다.

profile
keep going on~

0개의 댓글