Search code examples
javaunixioblocking

Having a Blocking write operation to a unix file


Is there some way to open a file on unix for writting that is blocking (that actually wait for the data to be in the file before completing the "write" operation ?

i'm having a program that takes result lines from a list and writes them in a file.

My current implementation is as follows (i removed the processing done on each line)

    ArrayList<String> lines = new ArrayList<>();
    BufferedReader in = new BufferedReader(new FileReader(inFile));
    String line;
    while((line = in.readLine()) != null){
      lines.add(line);
    }
    int written = 0;
    PrintWriter out = new PrintWriter(new FileWriter(outFile));
    for(String l : lines){
      written++;
      out.println(l);
      if(written % 10000 == 0)
        Message.info("lines written "+written);
    }
    out.close();

The current behaviour is the following :
[17:12:43 INFO ] lines written 10000
[17:12:43 INFO ] lines written 20000
[17:12:43 INFO ] lines written 30000
[17:12:44 INFO ] lines written 40000
[17:12:44 INFO ] lines written 50000
[17:12:44 INFO ] lines written 60000
[17:12:45 INFO ] lines written 70000
[17:12:45 INFO ] lines written 80000
[17:12:45 INFO ] lines written 90000
[17:12:46 INFO ] lines written 100000

Where the program runs very fast, but at the end, waits (30-40secondes) for all the data (4Go) to be written to the file before ending. (i can see the file growing on the disk during this time)
When what i want, is for my INFO message to be displayed only when the data are really in the file : the program will seem slower, but will end immediatly after the last message.

I tried using BufferedWriter (from new BufferedWriter() and Files.newBufferedWriter()), FileOutputStream, OutputStream, but all of those seem to propose only non-blocking IO operation

The program is run on Ubuntu (I read that the implementation is filesystem dependant)

So, is there some way to wait for a println()/write() operation to be complete before execution the next line of code ?

I "feel" that java as delegated the actual writing to the OS, and doesn't wait for the data to be on the disk to go on, but since java waits for the last write to be complete before exiting, there must be a way the wait after each line


Solution

  • The dirty workaround : Every 10,000 lines, I close the file and open it again using StanddardOpenOption.APPEND.
    This has the expected behaviour with only an acceptable time overhead.

    The clean solution : open the file with `StanddardOpenOption.SYNC.
    This has the expected behaviour with a STRONG time overhead