Java での ObjectOutputStream – オブジェクトをファイルに書き込む

ObjectOutputStreamは、JavaでオブジェクトをOutputStreamに変換するために使用することができます。オブジェクトをストリームに変換するプロセスは、Javaでのシリアリゼーションと呼ばれます。オブジェクトが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を使用したファイルへのオブジェクトの書き込みの例

オブジェクトをファイルに保存するためには、まずいくつかのプロパティを持つクラスが必要です。ファイルに保存するオブジェクトを作成しましょう。

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);
			// write object to file
			oos.writeObject(emp);
			System.out.println("Done");
			// closing resources
			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 キーワードを使用する必要があります。たとえば、以下のように role プロパティを変更すると保存されません。

private transient String role;

ObjectOutputStream と serialVersionUID

Employee オブジェクトで定義されている serialVersionUID に気づきましたか?これは、ObjectOutputStream および ObjectInputStream クラスがオブジェクトの書き込みおよび読み取り操作に使用します。このフィールドを持つ必要はないですが、保持しておくべきです。そうしないと、クラスを変更しても以前にシリアライズされたオブジェクトに影響を与えず、エラーが発生する可能性があります。詳細な分析については、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());
// 出力は "Employee:: Name=Pankaj Age=35 Gender=Male Role=CEO"

これがJava ObjectOutputStreamについてのすべてで、オブジェクトをファイルに書き込む方法です。

さらにJava IOの例は、GitHubリポジトリからチェックアウトできます。

参考: APIドキュメント

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