상세 컨텐츠

본문 제목

보조스트림 (InputStreamReader, ObjectInputStream writeObject)

기록 - 프로그래밍/Java

by wjjun 2024. 3. 5. 12:13

본문

 

보조스트림은 다른 스트림과 연결되어 다양한 기능을 제공하는 스트림입니다.

문자변환, 입출력 성능향상, 기본 데이터타입 입출력, 객체 입출력 등의 기능을 제공합니다.

 

콘솔 입력 스트림을 문자변환 보조 스트림 InputStreamReader에 연결하는 코드

InputStream is = System.in;
InputStreamReader reader = new InputStreamReader(is);

 

성능향상 보조 스트림 BufferedReader로 연결하는 코드

InputStream is = System.in;
InputStreamReader reader = new InputStreamReader(is);
BufferedReader br = new BufferedReader(reader);

 

문자 변환 보조 스트림

Reader, Write는 문자 단위 입출력으로 바이트 기반 스트림 보다 편하고 문자셋의 종류를 지정할 수 있어 다양한 문자 입출력이 가능합니다.

 

InputStreamReader

바이트 입력 스트림에 연결되어 문자 입력 스트림인 Reader로 변환시키는 보조 스트림

 

OutputStreamWriter

바이트 출력 스트림에 연결되어 문자 출력 스트림인 Writer로 변환시키는 보조 스트림

 

성능향상 보조 스트림

프로그램 실행 성능은 입출력이 가장 늦은 장치를 따라간다.

프로그램은 직접 하드 디스크에 데이터를 보내지 않고 메모리 버퍼에 데이터를 보내어 쓰기 속도를 향상시킨다. 버퍼는 데이터가 쌓이는 것을 기다리고 꽉찰 때 데이터를 한번에 하드 디스크로 보내어 출력 횟수가 줄어든다.

 

바이트 기반 스트림에는 BufferedInputStream, BufferedOutputStream이 있고, 문자 기반 스트림에는 BufferedReader, BufferedWriter 가 있다.

 

BufferedOutputStream, BufferedWriter

프로그램에서 전송한 데이터를 내부 버퍼에 쌓아두고 버퍼가 꽉 차면 버퍼의 모든 데이터를 한번에 보낸다

 

 

객체 입출력 보조 스트림

객체를 출력하기 위해서 객체의 데이터(필드값)를 일렬로 연속적인 바이트로 변경해야 하는데 이것이 직렬화다.

반대로 파일에 저장되었거나 네트워크에서 전송된 객체를 읽기 위해 입력 스트림으로부터 읽어드린 연속적인 바이트를 객체로 복원하는 것을 역직렬화다.

 

ObjectInputStream, ObjectOutputStream

ObjectOutputStream은 바이트 출력 스트림과 연결되어 객체를 직렬화하는 역할을 한다. ObjectInputStream은 바이트 입력 스트림과 연결되어 객체로 역직렬화 하는 역할을 한다. 

 

 

직렬화가 가능한 클래스(Serializable)

자바는 Serializable 인터페이스를 구현한 클래스만 직렬화 할 수 있도록 제한한다.

Serializable 인터페이스는 필드나 메서드 없는 빈 인터페이스이지만 객체를 직렬화할 때 private 필드를 포함한 모든 필드를 바이트로 변환해도 좋다는 표시 역할을 한다.

public class XXX implements Serializable { }

 

객체를 직렬화하면 바이트로 변환되는 것은 필드들이고, 생성자 및 메서드는 직렬화에 포함되지 않는다.

필드 선언에 static 또는 transient가 붙어 있을 경우에는 직렬화가 되지 않는다

 

serialVersionUID 필드

직렬화된 객체를 역직렬화할 때는 직렬화했을 때와 같은 클래스를 사용해야 합니다. 클래스 이름이 같아도 클래스 내용이 변경되면 역직렬화는 실패하며 에러가 발생합니다.

java.io.InvalidClassException: XXX; local class incompatible: stream classdesc serialVersionUID

 

serialVersionUID는 같은 클래스임을 알려주는 식별자 역할입니다.

 

 

writeObject(), readObject() 메서드

자식 클래스만 Serializable 인터페이스를 구현하고 있다면 자식 객체를 직렬화할 때 부모의 필드는 직렬화에서 제외된다. 이 경우 부모 클래스의 필드를 직렬화 하고 싶다면 두 가지 방법이 있다.

 

writeObject() 메서드는 직렬화 시 자동으로 호출되고 readObject() 메서드는 역질렬화 시 자동으로 호출된다.

단, private을 붙여줘야 자동 호출이 가능하다.

private void writeObject(ObjectOutputStream out) throws IOExcetpion {
    out.writeXXX(부모필드); // 부모 객체 필드값을 출력함
    out.defaultWriteObject(); // 자식 객체의 필드값을 직렬화
}

관련글 더보기

댓글 영역