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

如何使用ObjectOutputStream向文件追加内容而非覆盖原有内容?

如何用ObjectOutputStream向文件追加内容而非覆盖?

嗨,这个问题我之前踩过坑!你现在的代码每次运行都会覆盖文件,核心原因是默认的FileOutputStream构造方法会清空原有内容重新写入。要实现追加,得从两个关键地方调整:


第一步:开启文件追加模式

首先,把FileOutputStream的构造方法改成带追加参数的版本:

File f = new File(address);
// 第二个参数true表示开启追加模式,不会覆盖原有内容
FileOutputStream fos = new FileOutputStream(f, true);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s);
oos.close(); // 别忘了关闭流!

不过别急,直接这么改会有隐藏问题——继续往下看。


第二步:解决序列化头部重复的问题

这里有个容易忽略的点:每次创建ObjectOutputStream时,它都会自动往文件开头写入一个序列化魔术头和版本号。如果直接追加,文件里会有多个这样的头部,之后用ObjectInputStream读取时会直接抛出错误,因为它只认第一个头部,后面的会被当成无效数据。

解决这个问题的最优方案是自定义一个AppendableObjectOutputStream,继承ObjectOutputStream并重写writeStreamHeader()方法,让它在追加模式下跳过头部写入:

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);
    }

    @Override
    protected void writeStreamHeader() throws IOException {
        // 调用reset()而不是写入默认头部,避免重复添加
        reset();
    }
}

然后在你的写入方法里,判断文件是否为空:如果是第一次写入(文件长度为0),就用普通的ObjectOutputStream;如果是追加,就用我们自定义的类:

File f = new File(address);
boolean isFirstWrite = f.length() == 0;
FileOutputStream fos = new FileOutputStream(f, true);
ObjectOutputStream oos;

if (isFirstWrite) {
    oos = new ObjectOutputStream(fos);
} else {
    oos = new AppendableObjectOutputStream(fos);
}

oos.writeObject(s);
oos.close();

读取追加后的文件注意事项

当你读取这个包含多个对象的文件时,需要循环读取直到遇到EOFException(表示文件读取完毕):

import java.io.EOFException;
import java.io.FileInputStream;
import java.io.ObjectInputStream;

// 读取示例
FileInputStream fis = new FileInputStream(f);
ObjectInputStream ois = new ObjectInputStream(fis);

try {
    while (true) {
        Object obj = ois.readObject();
        // 在这里处理读取到的对象
        System.out.println(obj.toString());
    }
} catch (EOFException e) {
    // 正常结束,文件已经读完
    System.out.println("所有对象读取完成");
} finally {
    ois.close();
}

这样调整后,每次运行你的方法就会把对象追加到文件末尾,而不会覆盖原有内容,同时也能保证后续读取的正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:59:14