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 등
BufferedInputStream / BufferedOutputStream은 스트림의 입출력 효율을 높이기 위해 버퍼를 사용하는 보조스트림이다.
한 바이트씩 입출력하는 것보다 버퍼(바이트배열)를 이용해서 한 번에 여러 바이트를 입출력하는 것이 빠르기 때문에 대부분의 입출력 작업에 사용된다.
BufferedInputStream(InputStream in, int size) :
-> 주어진 InputStream 인스턴스를 입력소스(input source)로 하며 지정된 크기(byte단위)의 버퍼를 갖는 BufferedInputStream인스턴스를 생성한다.
BufferedInputStream(OutputStream out) :
-> 주어진 InputStream 인스턴스를 입력소스(input source)로 하며 버퍼의 크기를 지정해주지 않으므로 기본적으로 8192byte 크기의 버퍼를 갖는다.
버퍼의 크기는 입력소스로부터 한 번에 가져올 수 있는 데이터의 크기로 지정하면 좋다.
보통 입력 소스가 파일이면 8192(8K) 정도의 크기로 하는 것이 보통이다.
BufferedOutputStream(OutputStream out, int size)
-> 주어진 OutputStream 인스턴스를 출력소스 (output source)로 하며 지정된 크기(단위byte)의 버퍼를 갖는 BufferedOutputStream 인스턴스를 생성한다.
BufferedOutputStream(OutputStream out)
-> 주어진 OutputStream 인스턴스를 출력소스(output source)로 하며 버퍼의 크기를 지정해주지 않으므로 기본적으로 8192 byte 크기의 버퍼를 갖는다.
flush()
-> 버퍼의 모든 내용을 출력소스에 출력한 뒤, 버퍼를 비운다.
close()
-> flush()를 호출해서 버퍼의 모든 내용을 출력소스에 출력하고, BufferedOutputStream 인스턴스가 사용하던 모든 자원을 반환한다.
BufferedOutputStream 역시 버퍼를 이용하여 출력소스와 작업한다.
입력과 반대로 write메서드를 이용한 출력이 버퍼에 저장된다.
버퍼가 가득 차면 그 때 버퍼의 모든 내용을 출력소스에 출력한다.
버퍼가 가득 찼을 때만 출력을 하기 때문에, 마지막에 채워진 내용은 버퍼에 남은 채 프로그램이 종료될 수 있다.
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을 닫아주는 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()만 호출하면 된다.