Reputation: 2667
After playing with PrintWriter
and files, I got a doubt about why do sometimes when I read my files immediately when I create them, there are inconsistencies, for example:
File file = new File("Items.txt");
int loopValue = 10;
try {
PrintWriter fout = new PrintWriter(file);
for (int i = 0; i < loopValue; i++) {
fout.print(i + " asdsadas" + System.lineSeparator());
}
//fout.flush(); <-- I know if I call flush or close this problem don't occur
//fout.close();
System.out.println("Here is the file:");
Scanner readFile = new Scanner(file);
while (readFile.hasNext()) {
System.out.println(readFile.nextLine());
}
} catch (FileNotFoundException e) {
System.err.println(e.getMessage());
}
If I run this code, I will read in console an empty file, something like this:
Here is the file:
But if I modify the loopValue
to something like 10000, I will have something like this:
Here is the file:
0 asdsadas
1 asdsadas
2 asdsadas
...
... continues
...
9356 asdsadas
9357 asdsadas
9358 <--- here ends, note that it doesnt end in the value 9999
I know that if I call flush()
or close()
before read the file I can rid of this problem, but why is this happening? When do PrintWriter
decide that is time to clean its buffer without I tell it when? and why when I close or flush the PrintWriter
this problem won't happen?
Thanks!
Upvotes: 5
Views: 1008
Reputation: 6573
From your question I take it that you already know that there is (or at least may be) a buffer involved which gets flushed on flush
and on close
.
As to when flushing happens automatically, the JavaDoc on PrintWriter says:
Unlike the PrintStream class, if automatic flushing is enabled it will be done only when one of the println, printf, or format methods is invoked, rather than whenever a newline character happens to be output.
Now, how and if buffering happens depends on the underlying OutputStream that is used (can be specified via the constructor). If you use a BufferedOutputStream, you can specify the size of the buffer. Although it is not explicitly mentioned in the docs, flushing also happens when the buffer is full.
The PrintWriter constructor taking a File that you are using in your example says
Creates a new PrintWriter, without automatic line flushing, with the specified file. This convenience constructor creates the necessary intermediate OutputStreamWriter, which will encode characters using the default charset for this instance of the Java virtual machine.
without making any additional guarantees as to what OutputStreamWriter it will create and which settings it will use.
Upvotes: 1
Reputation: 22972
Buffering is a basic and important technique for speeding I/O
When you call close
it will releases all system resources associated with it here file will be used by Printwriter
and has not been saved your changes till now until you flush it. So that Scanner
which is trying to read file will get the old unchanged content.Now when you call flush
it just flushes the file and forces the writer to write all buffered bytes
till then stream buffers your input and than write to the file.Note here that you should use finally
block to close
the stream and note that close()
by default flush the stream for you but here you want to use it in line you better use flush and than close it in finally
block.
Upvotes: 1
Reputation: 521103
The general concept and motivation behind the buffer for PrintWriter
is that it is expensive to write something out to the console. Hence, by queueing up pending changes to be output, the program can run more efficiently. Imagine you had a Java program which were doing something very intensive from a CPU point of view, such as heavy calculations in a multithreaded application. Then, if you were also insisting that each call to PrintWriter.print()
deliver its output immediately, the program could hang, and overall performance would decline.
If you insist on seeing the output from PrintWriter
immediately after the call, then you can call flush()
to achieve this. But as already mentioned, there could be a performance penalty under certain conditions.
Upvotes: 3