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

Java使用FileReader与FileWriter读写同一文件时内容被清空问题

问题原因

FileWriter 仅传入文件对象/路径的默认构造方法,底层会调用 FileOutputStream(File file, boolean append),其中 append 参数默认值为 false,对应操作系统层面的文件打开标志为 O_TRUNC,只要以该模式打开已存在的普通文件,操作系统会直接将文件长度截断为0,原有内容立刻清空。这个行为和JVM锁、流的创建顺序完全无关,是文件打开模式的原生特性。
如果创建FileWriter时调用new FileWriter(testFile, true)的重载,将append参数设为true,打开文件时就不会清空原有内容,但这种模式下写入指针默认在文件末尾,无法实现覆写原有内容的需求,且同时打开读写流依然会有指针位置冲突的问题。

和FileDescriptor的关系

FileDescriptor 只是操作系统文件句柄的Java包装对象,本身不会决定文件打开后的行为,清空内容完全是由创建输出流时传入的覆写/追加模式决定的,和FileDescriptor没有直接关联。

同一文件同时读写的实现方案

方案1:小文件场景:先全量读取再写入

如果文件体积不大,最简单的方式是先把文件所有内容读到内存缓冲区,关闭读流后再打开写流写入目标内容,完全规避同文件同时打开读写流的冲突:

@Test
public void testCopyStream() throws IOException {
    File workingDir = new File(System.getProperty("user.dir"));
    File testFile = new File(workingDir, "test.txt");
    // 第一步:先全量读取内容
    String content = Files.readString(testFile.toPath());
    // 第二步:写入内容,需要追加就传入第二个参数true,需要覆写就用默认模式
    FileWriter fos = new FileWriter(testFile);
    fos.write(content); // 可替换为处理后的内容
    fos.close();
}

方案2:大文件/需要随机读写场景:使用RandomAccessFile

RandomAccessFile 支持以rw(读写)模式打开文件,打开时不会截断原有内容,还可以通过getFilePointer()、seek()方法控制读写指针的位置:

@Test
public void testRandomAccess() throws IOException {
    File workingDir = new File(System.getProperty("user.dir"));
    File testFile = new File(workingDir, "test.txt");
    try (RandomAccessFile raf = new RandomAccessFile(testFile, "rw")) {
        // 先读取所有内容
        byte[] buf = new byte[(int) raf.length()];
        raf.readFully(buf);
        String content = new String(buf, StandardCharsets.UTF_8);
        // 指针移到文件开头,需要追加就改为 raf.seek(raf.length())
        raf.seek(0);
        // 写入处理后的内容
        raf.write(content.getBytes(StandardCharsets.UTF_8));
        // 如果新写入内容比原文件短,需要截断剩余内容
        raf.setLength(raf.getFilePointer());
    }
}

如果一定要用字符流同时读写,也可以基于RandomAccessFile包装InputStreamReader、OutputStreamWriter实现,避免默认FileWriter打开即清空的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:15:04