java中连续读写多个对象需自定义objectoutputstream跳过重复流头,并用eofexception判断读取结束,对象须实现serializable且serialversionuid一致。

Java 中连续写入多个对象到文件并完整读取,核心是使用 ObjectOutputStream 和 ObjectInputStream,但必须注意:默认情况下它们不支持多次写入/读取(会因流头重复或 EOF 异常失败)。关键在于统一序列化协议、避免重复写入流头、正确处理读取边界。
写入多个对象:避免重复写入 STREAM_MAGIC
每次新建 ObjectOutputStream 都会写入 2 字节的流标识(STREAM_MAGIC),导致后续读取失败。解决方法是自定义子类跳过重复写头:
- 继承
ObjectOutputStream - 重写
writeStreamHeader()方法,在非首次调用时直接返回 - 使用同一个流实例连续写入多个对象(不能每次 new)
读取多个对象:循环直到 EOF
ObjectInputStream 没有内置“有多少对象”的元信息,需靠捕获 EOFException 判断结束:
- 用同一个
ObjectInputStream实例反复调用readObject() - 用 try-catch 捕获
EOFException作为正常终止信号 - 注意:
IOException或其他异常才是真实错误,不能一概当作结束
对象必须可序列化且类型一致
所有写入对象需实现 Serializable 接口,且读取端类定义(包名、类名、serialVersionUID)必须与写入时完全一致,否则抛 InvalidClassException。
- 建议显式声明
private static final long serialVersionUID = 1L; - 避免使用匿名内部类、Lambda 表达式等不可序列化类型
- 含非序列化字段(如
transient或静态字段)会被跳过,不影响读取
完整示例(写入 + 读取)
以下代码演示安全写入 3 个 User 对象,并完整读回:
// 自定义输出流(跳过重复 header)
class AppendableObjectOutputStream extends ObjectOutputStream {
public AppendableObjectOutputStream(OutputStream out) throws IOException {
super(out);
}
@Override
protected void writeStreamHeader() throws IOException {
reset(); // 重置对象引用表,避免 InvalidClassException
}
}
// 写入
try (FileOutputStream fos = new FileOutputStream("users.dat", true);
AppendableObjectOutputStream oos = new AppendableObjectOutputStream(fos)) {
oos.writeObject(new User("Alice", 25));
oos.writeObject(new User("Bob", 30));
oos.writeObject(new User("Charlie", 35));
} // 自动关闭
// 读取
List<user> users = new ArrayList();
try (FileInputStream fis = new FileInputStream("users.dat");
ObjectInputStream ois = new ObjectInputStream(fis)) {
while (true) {
try {
User u = (User) ois.readObject();
users.add(u);
} catch (EOFException e) {
break; // 正常结束
}
}
}
</user>
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











