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 示例,将对象写入文件

让我们来看一个 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 方法。它也没有无参数构造函数。以下是演示如何在 Java 中使用 ObjectOutputStream 将对象写入文件的程序。

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关键字。例如,只需像下面这样更改role属性,它就不会被保存。

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());
//输出将是 "Employee:: Name=Pankaj Age=35 Gender=Male Role=CEO"

这就是关于Java ObjectOutputStream以及如何使用它将对象写入文件的全部内容。

您可以从我们的GitHub代码库中查看更多Java IO示例。

参考:API文档

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