Using flush() before close()
Asked Answered
L

4

53

As per the java docs, invoking close() on any java.io Streams automatically invokes flush(). But I have seen in lot of examples, even in production codes, developers have explicitly used flush() just before close(). In what conditions we need to use flush() just before close()?

Locule answered 25/3, 2012 at 7:10 Comment(3)
This question may help you a little bit [see this][1] [1]: https://mcmap.net/q/340815/-when-to-use-flush-in-javaExurbanite
@Siva: as per the Javadoc. Quote and link, or it doesn't exist. As far as I know, some stream implementations will flush on close, while others won't. Do prove me wrong if that's not the case and the Javadoc says otherwise.Unconcern
Same question as haylem. I read through Java API documentation of a few classes and some say that flush() is called in close() while others don't make any such comment. Any link?Monger
L
32

Developer get into a habit of calling flush() after writing something which must be sent.

IMHO Using flush() then close() is common when there has just been a write e.g.

// write a message
out.write(buffer, 0, size);
out.flush();

// finished
out.close();

As you can see the flush() is redundant, but means you are following a pattern.

Lunette answered 25/3, 2012 at 7:45 Comment(2)
redundant + pattern = anti-pattern?Eade
Depending on the implenting class this might not be redundant. E.g if someinterface.getOutputStream() returns an OutputStream, you might not know if the close method calls flush or if the flush method is empty, if it's not explicitly documented. E.g. URLConnection.getOutputStream(): docs.oracle.com/javase/8/docs/api/java/net/…Wengert
C
32

I guess in many cases it's because they don't know close() also invokes flush(), so they want to be safe.

Anyway, using a buffered stream should make manual flushing almost redundant.

Cartridge answered 25/3, 2012 at 7:48 Comment(3)
Upvoted. Anybody, actually, should not assume that all close() also invokes flush().Flicker
@JinKwon They are perfectly entitled to do that for any output stream that extends FilterOutputStream: see the Javadoc.Cryan
The statement "they don't know close() also invokes flush()" is misleading, it's not always the case.Coruscation
G
11

I want to point out an important concept that many previous comments have alluded to:

A stream's close() method does NOT necessarily invoke flush().

For example org.apache.axis.utils.ByteArray#close() does not invoke flush().
(click link to see source code)

The same is true more generally for any implementations of Flushable and Closeable. A prominent example being java.io.PrintWriter. Its close() method does NOT call flush().
(click link to see source code)

This might explain why developers are cautiously calling flush() before closing their streams. I personally have encountered production bugs in which close() was called on a PrintWriter instance without first calling flush().

Gradeigh answered 6/5, 2019 at 22:20 Comment(2)
Both examples provided are essentially thin wrapper classes, so their flush and close implementations delegate to the underlying stream. I can't see how this alone could lead to any problems, as long as any "real" or buffering streams do flush when being closed.Employment
However I realize that the behavior is not (and can't be) enforced by the javadoc of Closeable.close().Employment
U
4

The answers already provided give interesting insights that I will try to compile here.

Closeable and Flushable being two independent traits, Closeable do not specify that close() should call flush(). This means that it is up to the implementation's documentation (or code) to specify whether flush() is called or not. In most cases it is the norm, but there is no guaranty.

Now regarding what @Fabian wrote: It is true that java.io.PrintWriter's close() method does not call flush(). However it calls out.close() (out being the underlying writer). Assuming out is a BufferedWriter, we are fine since BufferedWriter.close() is flushing (according to its doc). Had it be another writer, it may not have been the case...

So you have two choices:

  • either you ensure that at least one inner Writer/Stream flushes by itself (beware in case of code refactoring),
  • or you just call flush() and you're on the safe side all the time.

Solution 2, requiring less work, is my preferred one.

Uninspired answered 18/12, 2019 at 14:22 Comment(1)
True, but not all Closable specifies it. For instance, OutputStream does not.Uninspired

© 2022 - 2024 — McMap. All rights reserved.