In PrintWriter, why doesn't the print() function also auto-flush?
Asked Answered
P

1

6

When looking at the PrintWriter contract for the following constructor:

public PrintWriter(OutputStream out, boolean autoFlush)

Creates a new PrintWriter from an existing OutputStream. This convenience constructor creates the necessary intermediate OutputStreamWriter, which will convert characters into bytes using the default character encoding.

Parameters:
out - An output stream
autoFlush - A boolean; if true, the println, printf, or format methods will flush the output buffer

See Also: OutputStreamWriter.OutputStreamWriter(java.io.OutputStream)

Notice the autoFlush flag only works on println, printf, and format. Now, I know that printf and format basically do the exact same thing as print except with more options, but I just don't see why they didn't include print as well in the contract. Why did they make this decision?

Presentiment answered 20/4, 2015 at 17:41 Comment(6)
My guess is that flushing needs to end the line, but I could be wrong.Mossback
PrintWriter is line buffered and only auto flushes on a new line. Not sure why it assumes printf will have a new line.Iconium
don't know if it's related somehow, but javadoc also 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. These methods use the platform's own notion of line separator rather than the newline character. "Doff
@PeterLawrey PrintStream is line buffered when PrintWriter is not. the javadoc told they're differentAugustusaugy
I know from experience that print is not flushed but printf is, even without the newline. I say this because I have an interacting program that looks for a final line of text pushed out and I am expecting that the last characters are not \n or \r\n.Presentiment
From a programming perspective, I don't see why flushing should only occur after a newline; I would think it should occur after the last character in a printX call. But there could be a convention that in general, after a newline is seen, conduct a flush operation?Presentiment
D
4

I suspect it's because the Java authors are making assumptions about performance:

Consider the following code:

public static void printArray(int[] array, PrintWriter writer) {
    for(int i = 0; i < array.length; i++) {
        writer.print(array[i]);
        if(i != array.length - 1) writer.print(',');
    }
}

You almost certainly would not want such a method to call flush() after every single call. It could be a big performance hit, especially for large arrays. And, if for some reason you did want that, you could just call flush yourself.

The idea is that printf, format, and println methods are likely going to be printing a good chunk of text all at once, so it makes sense to flush after every one. But it would rarely, if ever, make sense flush after only 1 or a few characters.


After some searching, I have found a citation for this reasoning (emphasis mine):

Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.

To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

<snip>

It often makes sense to write out a buffer at critical points, without waiting for it to fill. This is known as flushing the buffer.

Some buffered output classes support autoflush, specified by an optional constructor argument. When autoflush is enabled, certain key events cause the buffer to be flushed. For example, an autoflush PrintWriter object flushes the buffer on every invocation of println or format.

Darr answered 20/4, 2015 at 18:11 Comment(4)
So basically, its a performance thing. They want to keep one of the printX functions non-autofushable so that the programmer can at least have some control over the flushing mechanism by hand.Presentiment
@Presentiment Realize that controlling flushing violates SRP, really. You shouldn't have to worry about flushing most of the time, they are trying to design the class so that clients (you) have to call flush as little as possible.Darr
Also, it's not about "one of the functions" it's about "generally speaking, print will not come close to filling the buffer, except in the case of print(String) or print(Object), but the others are much more likely to do so."Darr
print() calls charOut.flushBuffer(); which flushes all.Untimely

© 2022 - 2024 — McMap. All rights reserved.