Java의 ObjectOutputStream – 파일에 객체 쓰기

Java에서 ObjectOutputStream은 오브젝트를 OutputStream으로 변환하는 데 사용할 수 있습니다. 오브젝트를 스트림으로 변환하는 과정은 Java에서 직렬화(serialization)라고 불립니다. 오브젝트가 Output Stream으로 변환되면 파일이나 데이터베이스에 저장하거나 네트워크를 통해 전송하거나 소켓 연결에 사용할 수 있습니다. 따라서 FileOutputStream을 사용하여 오브젝트를 파일에 쓸 수 있습니다.

ObjectOutputStream

ObjectOutputStream은 Java IO 클래스의 일부이며, 그 목적은 Java 오브젝트를 스트림으로 변환하는 방법을 제공하는 것입니다. ObjectOutputStream의 인스턴스를 생성할 때 사용할 OutputStream을 제공해야 합니다. 이 OutputStream은 ObjectOutputStream에 의해 하위 출력 스트림(예: FileOutputStream)에 대한 오브젝트 스트림을 전달하는 데 사용됩니다.

ObjectOutputStream 요구사항

우리가 직렬화하려는 객체는 java.io.Serializable 인터페이스를 구현해야합니다. Serializable은 단순히 마커 인터페이스이며 구현해야 할 추상 메서드가 없습니다. 클래스가 Serializable 인터페이스를 구현하지 않은 경우 java.io.NotSerializableException을 얻게됩니다. 아래와 같은 예외 스택 트레이스와 같은 것입니다.

java.io.NotSerializableException: com.journaldev.files.EmployeeObject
	at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1184)
	at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
	at com.journaldev.files.ObjectOutputStreamExample.main(ObjectOutputStreamExample.java:21)

파일에 객체를 쓰는 Java ObjectOutputStream 예제

파일에 객체를 쓰기 위한 Java ObjectOutputStream 예제를 살펴보겠습니다. 우선, 몇 가지 속성이있는 클래스가 있어야합니다. 파일에 저장할 객체를 만들어 보겠습니다.

package com.journaldev.files;

import java.io.Serializable;

public class Employee implements Serializable {

	private static final long serialVersionUID = -299482035708790407L;

	private String name;
	private String gender;
	private int age;

	private String role;
	// private transient String role;

	public Employee(String n) {
		this.name = n;
	}

	public String getGender() {
		return gender;
	}

	public void setGender(String gender) {
		this.gender = gender;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getRole() {
		return role;
	}

	public void setRole(String role) {
		this.role = role;
	}

	@Override
	public String toString() {
		return "Employee:: Name=" + this.name + " Age=" + this.age + " Gender=" + this.gender + " Role=" + this.role;
	}

}

모든 속성에 대해 getter/setter를 가져야하는 요구 사항이 아닌 것에 유의하십시오. 또는 무인자 생성자를 가져야합니다. 위의 Employee 객체에는 “name” 속성에 대한 getter/setter 메서드가 없습니다. 그리고 무인자 생성자도 없습니다. 다음은 ObjectOutputStream을 사용하여 Java에서 파일로 객체를 쓰는 방법을 보여주는 프로그램입니다.

package com.journaldev.files;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectOutputStreamExample {

	public static void main(String[] args) {
		Employee emp = new Employee("Pankaj");

		emp.setAge(35);
		emp.setGender("Male");
		emp.setRole("CEO");
		System.out.println(emp);
		
		try {
			FileOutputStream fos = new FileOutputStream("EmployeeObject.ser");
			ObjectOutputStream oos = new ObjectOutputStream(fos);
			// 객체를 파일에 쓰기
			oos.writeObject(emp);
			System.out.println("Done");
			// 리소스 닫기
			oos.close();
			fos.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

다음 이미지는 위 프로그램의 출력을 보여줍니다. 만약 EmployeeObject.ser 파일의 내용이 궁금하다면, 약간 난해하고 아래와 같을 것입니다.

��srcom.journaldev.files.Employee�����yyIageLgendertLjava/lang/String;Lnameq~Lroleq~xp#tMaletPankajtCEO

transient를 사용한 ObjectOutputStream

스트림으로 변환되기를 원치 않는 객체 속성이 있다면 해당 속성에 대해 transient 키워드를 사용해야 합니다. 예를 들어 역할 속성을 아래처럼 변경하면 저장되지 않습니다.

private transient String role;

ObjectOutputStream와 serialVersionUID

Employee 객체에 정의된 serialVersionUID를 주목했나요? 이는 ObjectOutputStreamObjectInputStream 클래스에서 객체 작성 및 읽기 작업에 사용됩니다. 이 필드가 필수는 아니지만 유지하는 것이 좋습니다. 그렇지 않으면 클래스를 변경해도 이전에 직렬화된 객체에 영향을 미치지 않으므로 실패할 수 있습니다. 자세한 분석은 Java에서 직렬화로 이동하세요. 프로그램이 제대로 작동했는지 궁금하다면 저장된 파일에서 객체를 읽기 위해 아래 코드를 사용하세요.

FileInputStream is = new FileInputStream("EmployeeObject.ser");
ObjectInputStream ois = new ObjectInputStream(is);
Employee emp = (Employee) ois.readObject();

ois.close();
is.close();
System.out.println(emp.toString());
//Output will be "직원:: 이름=Pankaj 나이=35 성별=남성 역할=CEO"

이것이 자바 ObjectOutputStream 및 파일에 객체를 쓰는 방법에 대한 모든 것입니다.

더 많은 자바 IO 예제는 우리의 GitHub 저장소에서 확인할 수 있습니다.

참고: API 문서

Source:
https://www.digitalocean.com/community/tutorials/objectoutputstream-java-write-object-file