首页 > 解决方案 > FileInputStream and FileOutputStream: Read and write to the same file

问题描述

I created a text file with the content "Hello" and I was trying to read these characters from the file and write it back to the same file again.

Assumptions: 1. the file now has the content "Hello" (Overwritten) 2. the file now has the content "HelloHello" (Appended) 3. the file now has the content infinite "Hello" (or an exception gets thrown)

Actual result: Original "Hello" characters gets deleted from the text file, and the file was left empty.

Actual test

    @Test
    public void testCopyStream() throws IOException {
        File workingDir = new File(System.getProperty("user.dir"));
        File testFile = new File(workingDir, "/test.txt");

        FileReader fin = new FileReader(testFile);
        FileWriter fos = new FileWriter(testFile);
        copyStream(fin, fos);
        fin.close();
        fos.close();
}

I have created the following method for "copying" the data in the InputStream to the OutputStream:

private void copyStream(Reader in, Writer out) throws IOException {
        int b;
        while ((b = in.read()) != -1) {
           out.write(b);
        }
    }

I tried using debugger to find out the problem, and the debugger shows b = in.read() was assigned -1 at the first iteration of the while loop. Then I executed the code step by step while inspecting the file's content and found that "Hello" keyword got deleted from the file right after statementfinal FileWriter fos = new FileWriter(testFile); gets executed.

I first thought this was due to the InputStream and OutputStream were pointed to the same file so the file gets sort of "locked" by JVM for execution safety?

So I tried swapping those two lines:

        FileWriter fos = new FileWriter(testFile);
        FileReader fin = new FileReader(testFile);
        

And the result turned out the same: the file content got eliminated right after the statement FileWriter fos = new FileWriter(testFile);

My questions is: why the content gets cleaned out by FileWriter?. Is this some behavior related to FileDescriptor? Is there a way to read and write to the same file?

Just FYI,

  1. copyStream() method is working fine, I have tested it with other tests.
  2. It's not about using append() method instead of write()

标签: javajava-io

解决方案


The statement FileWriter fos = new FileWriter(testFile); truncates the existing file.

It does not make sense for you to use streaming access to read and write the same file, as this won't give reliable results. Use RandomAccessFile if you want to read / write the same file: this has calls to seek current position and perform read or writes at different positions of a file.

https://docs.oracle.com/javase/7/docs/api/java/io/RandomAccessFile.html


推荐阅读