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

Java序列化追加对象报错:无效类型码AC 求修复方案及代码

问题根源

第二次追加写入时,ObjectOutputStream会自动写入序列化流头部信息,而ObjectInputStream只会识别第一个头部,后续重复的头部会被判定为无效类型码,引发"无效类型码AC"错误。另外读取时用readObject() != null判断结束是错误的——流到达末尾时会抛出EOFException,而非返回null。


修复后的写入代码

首先需要自定义一个跳过流头部的AppendableObjectOutputStream,避免追加时重复写入头部:

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;

public class AppendableObjectOutputStream extends ObjectOutputStream {
    public AppendableObjectOutputStream(OutputStream out) throws IOException {
        super(out);
    }

    // 覆盖writeStreamHeader方法,追加写入时跳过头部
    @Override
    protected void writeStreamHeader() throws IOException {
        reset(); // 重置流状态,避免头部重复写入
    }
}

然后修改写入逻辑,判断文件是否为空:为空时用普通ObjectOutputStream写入头部,否则用自定义类追加对象:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.List;

public class SerializationHelper {
    public static void saveProducts(String filename, List<Product> productList) {
        File targetFile = new File(filename);
        boolean isFileEmpty = !targetFile.exists() || targetFile.length() == 0;

        try (FileOutputStream fos = new FileOutputStream(targetFile, true);
             ObjectOutputStream out = isFileEmpty ? new ObjectOutputStream(fos) : new AppendableObjectOutputStream(fos)) {

            for (Product pro : productList) {
                out.writeObject(pro);
                System.out.println(pro);
            }

            System.out.println("对象已成功保存");
            productList.clear();
        } catch (IOException ex) {
            System.out.println("捕获到IOException");
            ex.printStackTrace();
        }
    }
}

修复后的读取代码

修改读取逻辑,通过捕获EOFException判断流结束,同时利用try-with-resources自动关闭流:

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;

public class DeserializationHelper {
    public static List<Product> loadProducts(String filename) {
        List<Product> newProductList = new ArrayList<>();

        try (FileInputStream file = new FileInputStream(filename);
             ObjectInputStream in = new ObjectInputStream(file)) {

            while (true) {
                try {
                    Product p1 = (Product) in.readObject();
                    newProductList.add(p1);
                    System.out.println(p1);
                    System.out.println("完成读取");
                    System.out.println("当前列表大小: " + newProductList.size());
                } catch (EOFException e) {
                    // 捕获EOFException表示已读到文件末尾
                    break;
                }
            }
            System.out.println("已到达文件末尾。");

        } catch (IOException ex) {
            System.err.println("读取产品数据时出错: " + ex.getMessage());
        } catch (ClassNotFoundException e) {
            System.err.println("反序列化时找不到类: " + e.getMessage());
        }

        return newProductList;
    }
}

额外注意事项

  • Product类必须实现Serializable接口,并且保持serialVersionUID固定一致,否则反序列化会失败。
  • 确保每次追加写入的对象类型统一,避免反序列化时出现类型转换错误。

内容的提问来源于stack exchange,提问作者Yanuja Thanabalasingam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:05:10