[Java] 보조 스트림

Bam·2024년 3월 23일
0

Java

목록 보기
90/98
post-thumbnail

보조 스트림

보조 스트림은 스트림의 기능을 보완하기 위해 다른 스트림과 연결되어 편의 기능을 제공해주는 스트림을 의미합니다. 보조 스트림은 실제로 입출력을 하는 스트림은 아니기 때문에 데이터를 입출력할 수는 없습니다. 또한 보조 스트림은 여러 보조 스트림과 연결되어 체인을 구성할 수 있습니다.

다음 코드는 txt 파일을 읽기 위해 FileInputStream을 사용하는 경우 입력 성능을 높이기 위해 버퍼를 이용하는 BufferedInputStream을 사용하는 코드입니다.

InputStream is = new FileInputStream("text.txt");	//기반 스트림 FileInputStream
BufferedInputStream bis = new BufferedInputStream(is);	//보조 스트림 BufferedInputStream

bis.read();	//보조 스트림으로부터 데이터 read

위 코드에서 실제 입력은 FileInputStream이 수행하고, BufferedInputStream은 입력 버퍼만을 제공합니다.

주로 사용되는 보조 스트림을 나열하면 다음과 같습니다.

보조 스트림기능
InputStreamReader바이트 스트림을 문자 스트림으로 변환
BufferedInputStream, BufferedOutputStream
BufferedReader, BufferedWriter
입출력 성능 향상
DataInputStream, DataOutputStream기본형 데이터 입출력
PrintStream, PrintWriter개행, 형식화된 문자열 출력
ObjectInputStream, ObjectOutputStream객체 입출력

문자 변환 스트림

바이트 스트림의 입출력 데이터가 문자라면 문자 스트림으로 변환하고 사용하는 것이 효율적입니다. 문자를 바로 입출력하거나 문자셋 등을 이용할 수 있다는 장점이 있습니다.

다음은 각각 파일 입출력에서 바이트 입력 스트림을 문자 입력 스트림으로, 바이트 출력 스트림을 문자 출력 스트림으로 변환하는 코드입니다.

InputStream is = new FileStream("파일 경로");
Reader reader = new InputStreamReader(is);

OutputStream os = new FileOutputStream("파일 경로");
Writer writer = new OutputStreamWriter(os);

성능 향상 스트림

저장 장치의 속도, 네트워크의 속도에 따라서 CPU, 메모리의 성능과는 상관없이 느린 쪽으로 입출력 처리 속도가 맞춰지게 됩니다. 따라서 이런 경우 직접 입출력을 하기보다 버퍼를 이용해서 어느정도 실행 성능을 향상시킬 수 있습니다.

버퍼는 데이터가 쌓이기를 기다리다가 데이터가 모두 차게되면 한 번에 목적지로 데이터를 전송하게 됩니다. 그렇기 때문에 출력에서는 출력 횟수를 줄여주고, 입력에서는 읽기 횟수를 줄여줘서 실행 성능 향상을 얻을 수 있게 됩니다.

버퍼는 바이트 입출력 스트림은 BufferedInputStream, BufferedOutputStream을 사용하고 문자 입출력 스트림은 BufferedReader, BufferedWriter를 사용합니다.


기본형 스트림

boolean, char, short, int, long, float, double과 같은 기본형 데이터를 입출력하고 싶다면 DataOutputStream, DataInputStream을 사용합니다.

두 스트림 클래스는 기본형 입출력을 위해 readXxxxx(), writeXxxxx() 메소드를 제공하고 있습니다. 이 메소드를 사용할 때 주의할 점이 있는데요. 기본형 데이터의 byte 크기가 모두 다르므로 출력한 데이터를 읽을 때 동일한 순서로 읽어야한다는 점입니다.


프린트 스트림

프린트 스트림인 PrintStream, PrintWriterprint(), println(), println() 메소드를 가지고 있는 보조 스트림 클래스입니다.

즉, 우리가 그동안 써왔던 println()과 같은 프린트 메소드는 이 프린트 스트림에 속하던 메소드였었습니다.

System.out.print()를 처음 소개드릴 때, System 클래스가 out을 호출하는데, 이 out이 바로 PrintStream의 인스턴스라고 설명드렸었습니다. 그리고 PrintStreamprint() 메소드를 통해 콘솔에 출력하는 것이 코드의 동작이었습니다. 무려 80번의 포스트 만에 떡밥을 회수했네요.

당시의 설명인데요. 이제는 이 코드를 이해하실 수 있으시겠죠?


객체 스트림

ObjectInputStream, OnjectOutputStream은 객체를 입출력할 수 있는 보조 스트림입니다.

자바에서는 생성된 객체를 파일이나 네트워크로 출력할 수 있습니다. 객체를 출력하기 위해서는 필드를 일렬로 늘어선 바이트로 변환해야하는데요. 이 과정을 직렬화(serialization)이라고 하고, 반대로 직렬화된 바이트를 객체의 필드값으로 다시 변환하는 것을 역직렬화(deserialization)이라고 합니다.

그래서 ObjectOutputStream은 바이트 출력 스트림에 보조되어 객체를 직렬화하고, ObjectInputStreaem은 바이트 입력 스트림에 보조되어 바이트를 역직렬화합니다.

다음 코드는 ObjectInputStream, OnjectOutputStream를 바이트 입출력 스트림과 연결하고 직렬화하고 역직렬화를 수행하는 코드입니다.

ObjectInputStream ois = new ObjectInputStream(바이트 입력 스트림);
ObjectOutputStream oos = new ObjectOutputStream(바이트 출력 스트림);

oos.writeObject(객체);	//직렬화
객체타입 변수명 = (객체타입) ois.readObject();	//역직렬화

Serializable 인터페이스와 직렬화

자바는 Serializable 인터페이스를 구현하고 있는 객체만 직렬화가 가능하도록 제한합니다. Serializable 인터페이스 내용이 없는 빈 인터페이스로 이 객체가 직렬화가 가능하다고 표시하는 정도의 용도로만 사용됩니다.

필드를 직렬화할 때 정적(static) 필드와 transient로 선언된 키워드를 제외한 필드만 직렬화를 수행합니다.

transient 키워드는 필드에서 사용되며, 해당 키워드가 붙은 필드는 직렬화 대상에서 제외합니다.

직렬화에 사용된 클래스와 역직렬화에 사용되는 클래스는 내용이 동일해야합니다. 이름이 같아도 내용이 다르면 역직렬화가 불가능합니다. 만약 내용이 달라도 직렬화된 필드를 가지고 있다면 serialVersionUID 상수를 통해 역직렬화를 가능하게 만들 수 있습니다.

serialVersionUID의 값이 같다면 내용이 조금 다르더라도 역직렬화가 가능해집니다.

0개의 댓글