You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 14:24:07