views:

204

answers:

8

Hi,

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?

+4  A: 

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.

Matt
+3  A: 

when I do operation2(), can I assume that bw.close() has completed successfully?

Yes

OscarRyz
A: 

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.

polygenelubricants
in which case he wouldn't *"do operation2()"* in first place.
OscarRyz
@Oscar: the original words are "WHEN I do `operation2()`". English is not my first language, but I think WHEN is stronger than IF, and it may or may not matter in this context.
polygenelubricants
*..English is not my first language..* mine neither and now, I'm totally confused :)
OscarRyz
@Oscar: what I understand is that in English, saying "if" something happens have a different implication than saying "when" something happens. "when" is stronger because the implication is that it will happen, it's only a question of timing. "if" has no guarantee that it will happen in the first place. That's precisely what I'm trying to emphasis here: `operation2();` is not a simple matter of "when". It's an "if".
polygenelubricants
+1  A: 

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.

leonbloy
+1  A: 

The JavaDoc for java.io.BufferedReader.clos() is taken exactly from the contract if fulfills with java.io.Reader.

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).

Jacob Tomaw
+1  A: 

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.

Daniel
+1  A: 

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?

Mike
A: 

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.

EJP