3

I am writing to a text file using a BufferedWriter but the BufferedWriter does not write to the file until the program I'm running is finished and I'm not sure how to update it as the BufferedWriter is supposedly writing. Here is some of my code that I have:

FileWriter fw = null;
try {
    fw = new FileWriter("C:/.../" + target + ".pscr",true);
    writer = new BufferedWriter(fw);
    writer.write(target);
    writer.newLine();
    writer.write(Integer.toString(listOfFiles.length));
    writer.newLine();
    for(int i=0; i < listOfFiles.length; i++){
        writer.write(probeArray[i] + "\t" + probeScoreArray[i]);
        writer.newLine();                               
    }                           
}
catch (IOException e1) {e1.printStackTrace();}
catch (RuntimeException r1) {r1.printStackTrace();}
finally {
    try {
        if(writer != null){
            writer.flush();
            writer.close();
        }
    }
    catch (IOException e2) {e2.printStackTrace();}
}

I do flush the BufferedWriter but still have no file as soon as it writes, but instead when the program finishes. Any suggestions?

Tim
  • 19,793
  • 8
  • 70
  • 95
Brandon
  • 41
  • 2
  • 5
  • You're not flushing it until just before you close it, so I'm not sure what you mean by your next-to-last sentence. – Michael Myers Feb 17 '10 at 22:53
  • I've read that it is supposed to flush all of the time that it's writing, but no file is created as something is supposed to write. – Brandon Feb 17 '10 at 23:01
  • No, it's supposed to flush whenever its buffer fills. If you want it to flush more often, you have to do that manually yourself. But why do you care? BufferedWriter is used for efficiency. If you don't want that, don't use it. But the file content is basically useless until it is complete in most situations. – user207421 Feb 17 '10 at 23:24
  • Do you think a PrintWriter would do anything differently? I realize that if I want the output immediately as it is processed that I probably shouldn't use a BufferedWriter, but what else would work? – Brandon Feb 17 '10 at 23:35
  • 1
    Can you please update your question to show the most correct non-working version of the code? – rob Feb 18 '10 at 00:40
  • @Brandon: Yes a PrintWriter with autoflush = true as constructor argument should work.. see my answer below – Tim Feb 18 '10 at 08:58

3 Answers3

3

You need to move the flush() call into the try block. For example after every newLine() call.

That said, the flush() in finally is superfluous as close() already implicitly calls it.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I believe I did tried that before and it didn't work but I did move it back to try it again and still the same result – Brandon Feb 17 '10 at 23:09
  • Then the file is apparently already opened/locked by something else inside the same program. What if you try to write it to a different file? E.g. "c:/test.txt" or so. – BalusC Feb 17 '10 at 23:11
  • The file is created only at that point in time. There are no other existing files with that name. – Brandon Feb 17 '10 at 23:32
  • 1
    What platform? What JVM version? Can't reproduce this here at WinXP with 1.6.0_17-b04. I've also never seen this issue before. Isn't the problem more in the way how you tested/verified if the lines were written/flushed? – BalusC Feb 17 '10 at 23:54
  • running in eclipse with JVM 1.6.0_17...how else could I test to see if it has been written/flushed besides checking to see if there was a file created? – Brandon Feb 18 '10 at 00:01
  • Yes.. But **how** are you currently checking it? F5'ing the file in Eclipse or so? Rather test it by writing to the stdout console instead of file, or check if file size grows in Windows explorer, or use a realtime file tailing program like TailXP (if you're using Windows). – BalusC Feb 18 '10 at 00:07
0

Skip the buffering completely:

You're only every printing whole lines as it is, so the benefits it offers over a PrintWriter is lost in the the example above, due to the flush calls after every line write.
As described here: http://java.sun.com/javase/6/docs/api/java/io/BufferedWriter.html

PrintWriter pw = null;
try {
    pw = new PrintWriter(new FileWriter("C:/.../" + target + ".pscr", true), true);
    pw.println(target);
    pw.println(Integer.toString(listOfFiles.length));
    for(int i=0; i < listOfFiles.length; i++)
        pw.println(probeArray[i] + "\t" + probeScoreArray[i]);
}

Last update:
Called the PrintWriter(Writer out, boolean autoFlush) constructor, which according to the Javadoc, has the following behavior:

autoFlush - if true, the println, printf, or format methods will flush the output buffer

If this doesn't work I don't know what will..

Tim
  • 19,793
  • 8
  • 70
  • 95
  • I tried both ways and nothing...plus neither the BufferedWriter nor the FileWriter has a writeln() method – Brandon Feb 17 '10 at 23:29
  • @Brandon: Sorry, didn't have an IDE handy.. Updated my second example to work with a PrintWriter http://java.sun.com/javase/6/docs/api/java/io/PrintWriter.html which should have automatic flushing enabled, and should thus work correctly. Might I ask _how_ you're testing if the file is flushed correctly while running the program? – Tim Feb 17 '10 at 23:44
  • well if it is flushed then a file would be created the first time something is processed and continue to output to the file...but it's not creating the file until the end after everything has been processed. – Brandon Feb 17 '10 at 23:48
  • I tried to implement the PrintWriter the same way as I did the BufferedWriter and that didn't work either... – Brandon Feb 18 '10 at 00:04
  • @Brandon: Did you call the correct PrintWriter and FileWriter constructors? Both should have a boolean true added, the first to indicate you want to autoflush on each line, the second to indicate enabling appending.. The code sample above should work as it is.. – Tim Feb 18 '10 at 08:41
  • i'll have to check on that...i'm not sure that i did or not – Brandon Feb 18 '10 at 19:15
0

Just to be completely clear, this is where you need to add the flush, if you want to flush each line as it's written:

for(int i=0; i < listOfFiles.length; i++){
    writer.write(probeArray[i] + "\t" + probeScoreArray[i]);
    writer.newLine();
    writer.flush(); // Make sure the flush() is inside the for loop
}

In your code, the flush() isn't happening until the end of the program, because the finally{} block doesn't execute until after the try{} or catch{} block has finished executing.

rob
  • 6,147
  • 2
  • 37
  • 56