보조스트림이란?
보조 스트림은 입출력 대상이 되는 파일이나 네트워크에 직접 쓰거나 읽는 기능이 없다.
말 그대로 보조 기능을 추가하는 스트림이다. 여러가지 스트림에 적용할 수 있다.
말 그대로 보조해주는 보조요소이다! 어떤 보조 스트림이 더해지느냐에 따라 스트림 기능이 추가된다.
보조 스트림, Wrapper 스트림
다른 스트림을 감싸고 있다는 의미 | 스스로는 입출력 기능이 없기에 생성자의 매개 변수로 다른 스트림을 받게되면 자신이 감싸고 있는 스트림이 읽거나 쓰는 기능 수행시 보조 기능을 추가한다.
FIilterInputStream
FilterOutputStream
- 보조 스트림의 상위 클래스이다. 모든 보조 스트림은 위 스트림을 상속받는다. 보조 스트림은 자료의 입출력을 직접할 수 없기에 다른 기반 스트림을 포함한다. 그래서 생성자는 다음과 같다.
protected FilterInputStream(InputStream in) | 생성자의 매개변수로 InputStream을 받음 |
public FilterOutputStream(OutputStream out) | 생정자의 매개변수로 OutputStream을 받음 |
위 생성자 말고 다른 생성자는 제공하지 않는다. 이들 클래스를 상속받은 보조 클래스도 상위 클래스에 디폴트 생성자가 없으므로 다른 스트림을 매개변수로 받아 상위 클래스를 호출해야한다.
여기서 기억해야할점은 보조 스트림의 생성자에 항상 기반 스트림만 매개변수로 전달되는 것은 아니라는 점이다. 때로는 또다른 보조 스트림을 매개변수로 전달받을 수도 있다.
이때 전달되는 보조 스트림은 내부적으로 기반 스트림을 포함하고 있다. 이런 경우 하나의 기반 스트림에 여러 보조 스트림 기능이 추가된다.
자주 사용되는 보조 스트림에 대해 알아보자!
InputStreamReader / OutputStreamWriter
- 바이트 단위로 자료를 읽게되면 한글과 같은 문자는 당연히 깨진다. 그래서 문자는 Reader나 Writer에서 상속받은 스트림을 사용하여 자료를 읽거나 써야한다. 그러나 여기서 문제가 있다. 바이트 자료로만 입력되는 스트림이 있기 때문이다. 대표적으로 System.in 스트림이다. 또, 네트워크에서 소켓이나 인터넷이 연결되었을 때 읽거나 쓰는 스트림은 바이트 단위인 InputStream과 OutputStream이다. 이렇게 생성된 바이트 스트림을 문자로 변환해주는 보조 스트림이 바로InputStreamReader / OutputStreamWriter 이다.
InputStreamReader(InputStream in) | InputStream 클래스를 매개변수로 받아 Reader 생성 |
InputStreamReader(InputStream in, Charset cs) | InputStream과 Charset 클래스를 매개변수로 받아 Reader 생성 |
InputStreamReader(InputStream in, CharsetDecoder dec) | InputStream과 CharserDecoder를 매개변수로 받아 Reader 생성 |
InputStreamReader(InputStream in, String charsetName) | InputStream과 String으로 문자 세트 이름을 받아 Reader 생성 |
Charset 문자 세트란 문자를 표현하는 인코딩 방식이다. 바이트 자료가 문자로 변환될 때 지정된 문자 세트가 적용된다.
명시하지 않으면 디폴트 문자세트가 적용됨.
모든 생성자는 바이트 단위로 읽어들이는 스트림을 매개변수로 받는다. 생성자에서 매개변수로 받은 InputStream이 자료를 읽으면 읽은 바이트 자료를 문자로 변환해준다.
표준 입출력 스트림인 System.out과 System.in은 모두 바이트 스트림이다. Scanner 클래스는 변환할 필요가 없어 콘솔 입력에 많이 쓰인다. 네트워크에서 쓰이는 클래스는 스트림을 생성하면 InputStream이나 OutputStream으로 생성된다. 예를 들어 채팅 프로그램을 만든다고 할 때 바이트 단위로 사용하면 영어로만 채팅을 해야하지만 이럴 경우 읽어들인 자료를 이 보조 클래스를 활용해 문자로 변환하여 사용하면 된다.
Buffered 스트림
입출력이 한 바이트나 문자 단위로 이루어지면 그 만큼 프로그램 수행 속도가 느려진다. 이 스트림은 내부적으로 8,192 바이트 크기의 배열을 가지고 있고, 이미 생성된 스트림에 배열 기능을 추가해 더 빠르게 입출력을 실행할 수 있는 버퍼링 기능을 제공한다. 한 바이트나 한 문자 단위로 처리할 때보다 훨씬 빠르게 처리할 수 있다.
BufferedInputStream | 바이트 단위로 읽는 스트림에 버퍼링 기능 제공 |
BufferedOutputStream | 바이트 단위로 출력하는 스트림에 버퍼링 기능 제공 |
BufferedReader | 문자 단위로 읽는 스트림에 버퍼링 기능 제공 |
BufferedWriter | 문자 단위로 출력하는 스트림에 버퍼링 기능 제공 |
생성자를 확인해보자.
BufferedInputStream(InputStream in) | InputStream 클래스를 생성자의 매개변수로 받아 BufferedInputStream 생성 |
BufferedInputStream(InputStream in, int size) | InputStream 클래스와 버퍼 크기를 생성자의 매개변수로 받아 BufferedInputStream 생성 |
제공되는 메소드는 다음과 같다.
int read() | BufferedReader 클래스 일반 메소드 문자 하나를 읽어 들임문자를 0~65535의 정수로 읽어 들이며 읽을 문자가 없는 경우 -1 리턴 |
int read(char[] cbuf, int off, int len) | BufferedReader 클래스 일반 메소드 문자 배열 cbuf 의 off 인덱스부터 len 개수만큼의 문자를 정수로 읽어 들임 문자가 없는 경우 -1 리턴 |
String readLine() | BufferdReader 클래스 일반 메소드 입력된 텍스트를 줄 단위('\n')로 읽어 들임 읽어 들일 문자가 없어지면 'null' 반환 |
void close() | BufferedReader 클래스 일반 메소드 스트림 사용 후 메모리에서 스트림을 해제할 때 사용 |
DataInputStream / DataOutputStream
위에서 배운 스트림은 사람이 읽고 쓰는 텍스트 형식의 자료였다. 이번 스트림은 메모리에 저장된 0,1 상태를 그대로 읽거나 쓴다. 그래서 자료형의 크기가 그대로 보존된다.
DataInputStream(InputStream in) | InputStream을 생성자의 매개변수로 받아 DataInputStream 생성DataOutputStream(OutputStream out) | OutputStream을 생성자의 매개변수로 받아 DataOutputStream 생성
DataInputStream 메서드 - 자료형별 메서드를 제공한다.
byte readByte() | 1바이트를 읽어 반환 |
boolean readBoolean() | 읽은 자료가 0이 아니면 true, 0이면 false 반환 |
char readChar() | 한 문자를 읽어 반환 |
short readShort() | 2바이트를 읽어 정수 값 반환 |
int readInt() | 4바이트를 읽어 정수 값 반환 |
long readLong() | 8바이트를 읽어 정수 값 반환 |
float readFloat() | 4바이트를 읽어 실수 값 반환 |
double readDouble() | 8바이트를 읽어 실수 값 반환 |
String readUTF() | 수정된 UTF-8 인코딩 기반으로 문자열을 읽어 반환 |
DataOutputStream 메서드 각 read()에 대응되는 메서드를 제공한다.
void writeByte(int v) | 1바이트 자료 출력 |
void writeBoolean(boolean v) | 1바이트 값 출력 |
void writeChar(int v) | 2바이트 출력 |
void writeShort(int v) | 2바이트 출력 |
void writeInt(int v) | 4바이트 출력 |
void writeLong(long v) | 8바이트 출력 |
void writeFloat(float v) | 4바이트 출력 |
void writeDouble(double v) | 8바이트 출력 |
void writeUTF(String str) | 수정된 UTF-8 인코딩 기반으로 문자열 출력 |
데이터를 그대로 읽고 쓰는 스트림이기 때문에 같은 정수형이라도 자료형에 따라 다르게 처리한다.
따라서 자료를 쓸 때 사용한 메서드와 같은 자료형의 메서드로 읽어야한다. 또, 자료를 쓸 때 사용한 메서드 순서대로 읽어야한다!
import java.io.*;
public class DataInOut2 {
public static void main(String[] args) throws Exception {
// 파일 저장
File f = new File("c:/webtest/3.java/data.txt");
FileOutputStream fos = new FileOutputStream(f);
// 자바의 자료형에 맞게 출력 하도록 보조 스트림 생성
DataOutputStream dos = new DataOutputStream(fos);
// 메모리의 자료형에 맞게 저장
char han = '한';
byte b = 21;
String str = "bg\n"; // \n : 줄바꿈
byte ba[] = { 65, 66, 67 }; // A, B, C 변환
// DataOutputStream 메소드를 사용해서 데이터 출력
dos.writeChar(han);
dos.writeByte(b);
dos.writeBytes(str);
dos.write(ba);
// 파일에 자료 출력 후 스트림 메모리 해제
dos.close();
fos.close();
// 자바의 자료형에 맞게 파일의 자료를 읽어오는 객체 생성
DataInputStream dis = new DataInputStream(new FileInputStream(f));
// 불러온 값을 새로운 변수에 저장
char c = dis.readChar();
byte b2 = dis.readByte();
String str2 = dis.readLine();
byte bb[] = new byte[3];
dis.read(bb);
System.out.println("c: " + c);
System.out.println("b2: " + b2);
System.out.println("str2: " + str2);
// 문자열을 byte[]로 반환, 주소값 출력
System.out.println("str2: " + str2.getBytes());
// 바이트 배열 주소값 출력
System.out.println("bb: " + bb);
// byte[]를 매개변수로 하는 생성자를 사용해서 String으로 출력
System.out.println(new String(bb));
/*
c: 한
b2: 21
str2: bg
str2: [B@15db9742
bb: [B@6d06d69c
ABC
*/
}
}
++ 보조 스트림은 자료형만 맞는다면 또 다른 보조 스트림에 기능을 더해 줄 수 있다!
'공부 STUDY > JAVA' 카테고리의 다른 글
[JAVA] File 클래스 | RandomAccessFile 클래스에 대해 알아보자 (0) | 2023.01.24 |
---|---|
[JAVA] 직렬화 (Serialization ), 역직렬화 (Deserialization) (0) | 2023.01.24 |
[JAVA] 자바 입출력과 스트림 - (4) | 문자 단위 스트림 (0) | 2023.01.24 |
[JAVA] 자바 입출력과 스트림 - (3) | 바이트 단위 스트림 - OutputStream (0) | 2023.01.24 |
[JAVA] 자바 입출력과 스트림 - (2) | 바이트 단위 스트림 - InputStream (0) | 2023.01.24 |