객체 입출력 보조 스트림
자바는 메모리에 생성된 객체를 파일 또는 네트워크로 출력할 수 있다. 객체는 문자가 아니기 때문에 바이트 기반 스트림으로 출력해야한다. 객체를 출력하기 위해서 객체의 데이터(필드값)을 일렬로 늘어선 연속적인 바이트로 변경해야 하는데, 이것을 객체 직렬화(serializaion)라고 한다.
반대로 파일에 저장되어 있거나 네트워크에서 전송된 객체를 읽을 수도 있는데, 입력 스트림으로부터 읽어들인 연속적인 바이트를 객체로 복원하는 것을 역직렬화(deserializaion) 라고 한다.
자바의 객체를 입출력할 수있는 두 개의 보조스트림인 ObjectInputSteam과 ObjectOutputStream을 제공한다.
ObjectOutputStream은 바이트출력스트림과 연결되어 객체를 직렬화하는 역할을 한다.
ObjectInputSteam은 바이트 입력 스트림과 연결되어 객체로 역직렬화하는 역할을 한다.
두 스트림은 연결할 바이트 입출력 스트림을 생성자의 매개값으로 받는다.
ObjectInputSteam ois = new ObjectInputSteam(바이트입력스트림);
ObjectOutputStream oos = new ObjectOutputStream(바이트출력스트림);
ObjectOutputStream으로 객체를 직렬화하기 위해서는 writeObject()메서드를 사용한다.
oos.writeObject(객체);
반대로 ObjectinputStream의 readObject() 메서드는 입력 스트림에서 읽은 바이트를 역직렬화해서 객체를 생성한다.
객체타입 변수 = (객체타입)ois.readObject();
직렬화 예제
public class ObjectIOTest {
public static void write() {
String fileName = "a.aer";
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream(fileName);
oos = new ObjectOutputStream(fos);
Date dt = new Date();
oos.writeObject(dt); //객체직렬화
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
직렬화가 가능한 클래스 (Serializable)
Serializable 인터페이스를 구현한 클래스만 직렬화할 수 있도록 제한하고 있다. Serializable인터페이스는 필드나 메서드가 없는 빈 인터페이스지만, 객체를 직렬화할 때 private필드를 포함한 모든 필드는 바이트로 변환해도 좋다는 표시 역할을 한다.
public class XXX implements Serializable{ }
객체를 직렬화하면 바이트로 변환되는 것은 필드들이고, 생성자 및 메서드는 직렬화에 포함되지 않는다. 따라서 역직렬화할 때에는 필드의 값만 복원된다. 하지만 모든 필드가 직렬화 대상이 되는 것은 아니다.
필드 선언에 static 또는 transient 가 붙어 있을 경우에는 직렬화가 되지 않는다.
public class exx implements Serializable{
public int field1;
protected int field2;
int field3;
private int field4;
public static int field5; // 직렬화 제외
transient int field6; // 직렬화 제외
}
▶ ser.txt 파일을 자동생성시키고 파일안에 FileOutputStream으로 바이트 단위로 데이터를 파일에 저장하고 ObjectOutputStream로 바이트 출력 스트림과 연결되어 객체를 직렬화하기
다음과 같이 구현해보았다.
String fileN = "ser.txt";
FileOutputStream fileOutput = null;
ObjectOutputStream objectOutput = null;
생성할 txt명을 String타입의 변수에 참조한다.
FileOutputStream는 바이트 단위로 데이터를 파일에 저장할 때 사용하는 바이트기반출력스트림이다.
ObjectOutputStream은 바이트 출력스트림과 연결되어 객체를 직렬화한다.
날짜를 출력하기 위해 Date() 메서드를 사용하여 객체 직렬화를 한다.
oos와 fos 가 null이 아니면 close() 메서드를 사용하여 사용한 버퍼를 없애는 작업을 한다.
주의할 점은 oos를 우선적으로 처리해주고 다음으로 fos를 처리한다.
try {
fos = new FileOutputStream(fileName);
oos = new ObjectOutputStream(fos);
Date dt = new Date();
oos.writeObject(dt); //객체직렬화
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(oos != null) {
try {
oos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fos != null) {
try {
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
역직렬화
FileInputStream 클래스는 파일로부터 바이트 단위로 읽어들일떄 사용하는 바이트 기반 입력 스트림이다.
ObjectInputStream은 바이트 입력스트림과 연결되어 객체로 역직렬화하는 역할을 한다.
직렬화에서 했던작업과 비슷하며 읽기위해 FileInputStream 와 ObjectInputStream를 사용하여 읽어들인 연속적인 바이트를 객체로 복원하는작업을 한다.
public static void read() { //역직렬화
String fileName = "a.ser";
FileInputStream fis = null;
ObjectInputStream ois = null;
try {
fis = new FileInputStream(fileName);
ois = new ObjectInputStream(fis);
//객채역직렬화 작업
Object obj = ois.readObject(); //객체 역직렬화
System.out.println(obj); //obj.tostring()자동호출
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if(ois != null) {
try {
ois.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if(fis != null) {
try {
fis.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
write();
read();
}
'java' 카테고리의 다른 글
java_17 스레드 (0) | 2021.11.01 |
---|---|
SOLID 객체지향설계 (0) | 2021.10.31 |
java_15_Io 패키지- 출력스트림(Writer) (0) | 2021.10.29 |
java_15_Io 패키지- 출력스트림(OutputStream) (0) | 2021.10.29 |
java_15_Io 패키지 - 입력스트림(Reader) (0) | 2021.10.29 |