Java向序列化文件追加对象后读取仅返回最新对象问题求解
Java序列化追加写入读取异常修复方案
错误原因
- 读取逻辑重复调用
readObject(),导致奇数位写入的对象被丢弃:你在while判断条件中已经执行了一次readObject(),读取的对象没有被处理直接丢弃,循环体中又执行了一次readObject(),每次循环实际读取两个对象仅处理第二个,因此仅会输出所有写入的第二个、第四个对象,也就是两次test2的属性。 - 追加序列化时流头处理逻辑错误:默认
ObjectOutputStream初始化时会写入序列化标识头,追加写入时如果重复写入头会导致读取时识别异常。你当前重写的writeStreamHeader方法调用reset()仅会重置对象引用缓存,并不会跳过流头写入,存在运行隐患。
修复代码
修复后的Main类
import java.io.*; public class Main implements Serializable { public static void main(String[] args) throws IOException, ClassNotFoundException { TestClass test = new TestClass(); test.username = "this one is first"; test.age = 23; test.phone = "+1 (010) 000 0000"; test.address = "2 Main St."; TestClass test2 = new TestClass(); test2.username = "this one is second 22222"; test2.age = 23; test2.phone = "+1 (010) 000 0000"; test2.address = "2 Main St."; // 第一次写入(文件不存在时创建,正常写流头) ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser")); out.writeObject(test); out.writeObject(test2); out.close(); // 追加写入,重写writeStreamHeader跳过新流头写入 ObjectOutputStream out2 = new ObjectOutputStream(new FileOutputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser", true)) { @Override protected void writeStreamHeader() throws IOException { // 追加模式不写入新的流头 } }; out2.writeObject(test); out2.writeObject(test2); out2.close(); ObjectInputStream in = new ObjectInputStream(new FileInputStream("C:\\Java Projects\\ObjectOutputStreamTests\\files\\test.ser")); try { // 直接循环读取,直到抛出EOFException表示读到文件末尾 while (true) { TestClass testRead = (TestClass) in.readObject(); System.out.println(testRead.username); System.out.println(testRead.age); System.out.println(testRead.address); System.out.println(testRead.phone); System.out.println("------"); } } catch (EOFException e) { System.out.println("end"); } finally { in.close(); } } }
TestClass无需修改
import java.io.Serializable; public class TestClass implements Serializable { public String username; public int age; public String phone; public String address; }
验证效果
修复后控制台会按顺序输出4个对象的属性:test、test2、test、test2,符合所有写入对象的预期输出。
内容的提问来源于stack exchange,提问作者WardenHelmet
相关产品推荐
相关产品推荐

