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()?
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.
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.
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().
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.
Related
Recently I was writing a http server and I transplanted some netty components to my project. When I read the source code of netty's ChannelHandlerContext, I found that actually it doesn't flush into socket. I knew that I have to invoke flush() to flush the internal buffer into socket.
So I wonder will netty automatically flush the internal buffer, I have read some source code, but I am not good at it. And I googled but none answered it, the only answer I got is do flushing.
What I have learned from source code is: write continue writing into outboundbuffer, and if outboundbuffer reaches highwatermark, it will fire writability changed event and the channel is unwritable.
You can call the writeAndFlush method if you want to do it in one line, but otherwise you need to flush or you data will not go through.
4.0 introduced a new operation called flush() which explicitly flushes the outbound buffer of a Channel, and write() operation does not flush automatically. You can think of this as a java.io.BufferedOutputStream, except that it works at message level.
Because of this change, you must be very careful not to forget to call ctx.flush() after writing something. Alternatively, you could use a shortcut method writeAndFlush().
I found it at https://netty.io/wiki/new-and-noteworthy-in-4.0.html#write-does-not-flush-automatically
In fact, I have the similar question at Why did not call ctx.flush() after ctx.write() is called at Netty user guide?
Please contact me if you got the answer.
No, it won't.
However, it could be implemented quite easily.
As you said:
What I have learned from source code is: write continue writing into
outboundbuffer, and if outboundbuffer reaches highwatermark, it will
fire writability changed event and the channel is unwritable.
It's right. and it in fact tells a way to automaticallly flush. Just override ChannelInboundHandler.channelWritabilityChanged to call flush().
Why in this classes (StringWriter, PrintWriter) method close has no effect as it mentioned in javadoc?
I understand that the simple not implemented I suppose. But why?
StringWriter doesnt have any resources on the file system unlike PrintWriter. It's close method just exists to satisfy the Closable interface.
The close() method on a StringWriter doesn't do anything because there isn't anything that needs to be done.
Now we can contrast that with other types of Writer (etcetera) that do need to do something at "close" time. For example:
A BufferedWriter needs to flush any buffered output ... so that it doesn't get lost.
A FileWriter needs to perform a close on the native file handle for the open open file. That needs to be done because if these handles are not closed, the JVM will run out, and "opens" will stop working.
But a StringWriter doesn't needs to do anything ... so it doesn't.
The StringWriter::close() method exists because it is actually implemented in its superclass.
The method exists in the superclass to make it (more) usable in polymorphic contexts. If close() was not implemented in Writer, then there would be two "kinds" of Writer (closeable and non-closeable) and application code that used writers would need to handle them differently.
As it is, applications can close all Writer objects, knowing that the right thing will be done. In some situations, the JIT compiler can optimize away a call to StringWriter::close(). In others, the overhead of a call to a no-op methods is rarely significant from a performance perspective.
I read this question Using flush() before close() , and the accepted answer is this only means you follow the pattern.
Just like BufferedWriter#close() or FilterOutputStream.#close() , if all of buffered Stream/Writer will call its flush() when we call close() and if we (the dev and the dev who will review the code) all know the that, do we really still need this? If yes, what will be the reason?
As the javadoc says, you don't need to flush yourself.
But, it's still good to do, considering your readers, and common sense.
Few experts know the javadoc by heart.
I wouldn't know for sure if the stream will be flushed or not without looking it up,
and I'm probably not alone.
Seeing the explicit flush() call makes this perfectly clear,
and therefore makes the code easier to read.
Furthermore, the method name close() implies nothing about flushing.
It's from the Closeable interface,
and naturally, it says nothing about flushing.
If you don't flush a buffered output stream before closing,
despite wanting to flush it,
you'll be relying on assumptions that may or may not be true.
It would weaken your implementation.
Any assumptions you make,
you should somehow pass on to future maintainers.
One way to do that is by leaving a comment:
// no need to flush() manually, close() will do it automatically
If you don't leave this comment,
future maintainers may have to lookup the javadoc too,
if like me they don't have it memorized.
But then, why would you write such comment when it's easier and better to just call it yourself now and be done with it.
In short, flushing first before closing is simply following good logic.
No need for assumptions and second guesses,
and no need to make your readers think.
For output, it is important that we do call flush() and close() because buffered data could be lost, as explained by the first answer here. If your program's output is smalland your writer finishes quickly, it won't make much difference to close() and flush() in my experience.
For input, it won't matter if we don't call close() before the system exits.
Assume that I have the following code fragment:
operation1();
bw.close();
operation2();
When I call BufferedReader.close() from my code, I am assuming my JVM makes a system call that ensures that the buffer has been flushed and written to disk. I want to know if close() waits for the system call to complete its operation or does it proceed to operation2() without waiting for close() to finish.
To rephrase my question, when I do operation2(), can I assume that bw.close() has completed successfully?
when I do operation2(), can I assume that bw.close() has completed successfully?
Yes
Close the stream, flushing it first. Once a stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously-closed stream, however, has no effect.
Though the documentation does not say anything specifically, I would assume this call does block until finished. In fact, I'm pretty sure nothing in the java.io package is non-blocking.
The JavaDoc for the java.io.BufferedReader.close() is taken exactly from the contract if fulfills with the java.io.Reader.
The Doc says:
Closes the stream and releases any system resources associated with it. Once the stream has been closed, further read(), ready(), mark(), reset(), or skip() invocations will throw an IOException. Closing a previously closed stream has no effect.
While this makes no explicit claim of blocking until the file system is complete, with this same instance of BufferedReader all other operations will throw an exception if close() returns. Although the JavaDoc could be seen as ambiguous about when the operation completes, if the file system flush and close were not complete when this method returned it would violate the spirit of the contract and be a bug in Java (implementation or documentation).
NO! You cannot be sure for the following reason:
A BufferedWriter is a Wrapper for another Writer. A close() to the BufferedWriter just propagates to the underlying Writer.
IF this underlying Writer is an OutputStreamWriter, and IF the OutputStream is a FileOutputStream, THEN the close will issue a system call to close the file handle.
You are completely free to even have a Writer where close() is a noop, or where the close is implemented non-blocking, but when using only classes from java.io, this is never the case.
A Writer (or BufferedWriter) is a black box that writes a stream of characters somewhere, not necessarily to the disk. A call to close() must (by method contract) flush its buffered content before closing, and should (normally) block before all its "essential" work is done. But this would depend on the implementation and the environment (you cannot know about caches that are below the Java layer, for example). In what respects of the work to be done by the Java writer itself (eg: make the system call to write to disk, in the case of a FileWriter or akin, and close the filehandle) , yes, you can assume that when close() returns it has already done all its work.
In general with any i/o operation you can make no assumptions about what has happened after the write() operation completes, even after you close. The idea of delivery is a subjective concept relative to the medium.
For instance, what if the writer represents a TCP connection, and then the data is lost inbetween client and server? Or what if the kernel writes data to a disk, but the drive physically fails to write it? Or if the writer represents a carrier pigeon that gets shot en route?
Furthermore, imagine the case when the write has no way of confirming that the endpoint has received the data (read: udp/datagrams). What should the blocking policy be in that situation?
The buffer will have been flushed to the operating system and the file handle closed, so the Java operations required will have been completed.
BUT the operating system will have cached or queued the write to the actual disk, pipe, network, whatever - there is no guarantee that the physical write has completed. FileChannel.force() provides a way to do that for files on local disks: see the Javadoc.
Yes, IF you reach operation2();, the stream would've had to have been completely closed. However, close() throws IOException, so you may not even get to operation2();. This may or may not be the behavior that you expect.
I have a question in my mind that, while writing into the file, before closing is done, should we include flush()??. If so what it will do exactly? dont streams auto flush??
EDIT:
So flush what it actually do?
Writers and streams usually buffer some of your output data in memory and try to write it in bigger blocks at a time. flushing will cause an immediate write to disk from the buffer, so if the program crashes that data won't be lost. Of course there's no guarantee, as the disk may not physically write the data immediately, so it could still be lost. But then it wouldn't be the Java program's fault :)
PrintWriters auto-flush (by default) when you write an end-of-line, and of course streams and buffers flush when you close them. Other than that, there's flushing only when the buffer is full.
I would highly recommend to call flush before close. Basically it writes remaining bufferized data into file.
If you call flush explicitly you may be sure that any IOException coming out of close is really catastrophic and related to releasing system resources.
When you flush yourself, you can handle its IOException in the same way as you handle your data write exceptions.
You don't need to do a flush because close() will do it for you.
From the javadoc:
"Close the stream, flushing it first. Once a stream has been closed, further write() or flush() invocations will cause an IOException to be thrown. Closing a previously-closed stream, however, has no effect."
To answer your question as to what flush actually does, it makes sure that anything you have written to the stream - a file in your case - does actually get written to the file there and then.
Java can perform buffering which means that it will hold onto data written in memory until it has a certain amount, and then write it all to the file in one go which is more efficient. The downside of this is that the file is not necessarily up-to-date at any given time. Flush is a way of saying "make the file up-to-date.
Close calls flush first to ensure that after closing the file has what you would expect to see in it, hence as others have pointed out, no need to flush before closing.
Close automatically flushes. You don't need to call it.
There's no point in calling flush() just before a close(), as others have said. The time to use flush() is if you are keeping the file open but want to ensure that previous writes have been fully completed.
As said, you don't usually need to flush.
It only makes sense if, for some reason, you want another process to see the complete contents of a file you're working with, without closing it. For example, it could be used for a file that is concurrently modified by multiple processes, although with a LOT of care :-)
FileWriter is an evil class as it picks up whatever character set happens to be there, rather than taking an explicit charset. Even if you do want the default, be explicit about it.
The usual solution is OutputStreamWriter and FileOutputStream. It is possible for the decorator to throw an exception. Therefore you need to be able to close the stream even if the writer was never constructed. If you are going to do that, you only need to flush the writer (in the happy case) and always close the stream. (Just to be confusing, some decorators, for instance for handling zips, have resources that do require closing.)
Another usecase for flushing in program is writing progress of longrunning job into file (so it can be stopped and restarted later. You want to be sure that data is safe on the drive.
while (true) {
computeStuff();
progresss += 1;
out.write(String.format("%d", progress));
out.flush();
}
out.close();