0

I have a java process A that calls FileOutputStream.flush() to flush the content, and have another process B to read the file content. In most cases, the process B reads the content fine. However, sometimes B reports getting incorrect content.

My question is, if the writer process crashes right after calling FileOutputStream.flush() before calling FileOutputStream.close(), can the java runtime guarantee that the reader can still read the full content that is written before flush? Must we call FileOutputStream.getFD().sync() to make sure that the file is written to disk?

The following is my test program on this case:

Writer: (note that I intentionally do not call FileOutputStream.close())

import java.io.File;
import java.io.FileOutputStream;

public class Main {

    public static void main(String[] args) throws Exception {

        for (int j = 0; j < 100; j++) {
            File file = new File("/tmp/test");
            if (file.exists()) {
                file.delete();
            }

            FileOutputStream outputStream = null;
            outputStream = new FileOutputStream("/tmp/mytest");
            String content = "";
            for (int i = 0; i < 100 - j; i++) {
                content += "," + Integer.toString(i);
            }

            outputStream.write(content.getBytes());
            outputStream.flush();
            System.exit(-1);
        }
   }
}

Reader:

import java.io.File;
import java.util.Scanner;

public class MyReader {

    public static void main(String[] args) throws  Exception {
        File file2 = new File("/tmp/mytest");
        Scanner sc = new Scanner(file2);

        while (sc.hasNextLine())
            System.out.println(sc.nextLine());
        sc.close();
    }

}
yuyang
  • 1,511
  • 2
  • 15
  • 40
  • What is the exact error message ? – Arnaud Jul 02 '18 at 07:28
  • Are you reading and writing the file simultaneously? – ISlimani Jul 02 '18 at 07:29
  • @DforTye we are not reading the file simultaneously. the reader only reads the file after the write exits. – yuyang Jul 02 '18 at 07:49
  • Note that you are not closing your `outputStream` . – Arnaud Jul 02 '18 at 07:50
  • @Berger that is my quesiton: if the writer process crashes right after calling FileOutputStream.flush() before calling FileOutputStream.close(), can the java runtime guarantee that the reader can still read the full content that is written before flush? – yuyang Jul 02 '18 at 07:53
  • 1
    See this question : https://codereview.stackexchange.com/questions/33010/do-i-need-to-close-my-fileoutputstreams – Arnaud Jul 02 '18 at 08:04
  • Fundamentally, filesystems are not communications channels. There's no real way to sequence reads after writes to guarantee full transfer of content, especially if you're using a platform such as Java which provides layers of abstraction from the native system. It seems easy to use them as such so this kind of misuse is rampant, but as you've found out doing so is not reliable. – Andrew Henle Jul 02 '18 at 10:48

1 Answers1

3

FileOutputStreamdoesn't use any buffer, so flush method is empty. Calling it or not is useless.

The source code of class FileOutputStream hasn't a custom version of method flush. So the flush method used is the version of its super class OutputStream. The code of flush in OutputStream is the following

public void flush() throws IOException {
}

See this answer for more infos:

flush and close

ISlimani
  • 1,643
  • 14
  • 16