While working on BufferedOutputStream
found it does not throw an IOException
when we wrote on it after closing the stream.
To verify my result, i checked FileOutputStream
found it is throwing IOException
once we try to write on it after closing it.
public class Test {
public static void main(String[] args) {
try {
// Created a byte[] barry1 barry2
byte[] barry1 = { '1', '3' };
byte[] barray2 = { '2', '4' };
OutputStream os = new BufferedOutputStream(
new FileOutputStream("abc.txt", false));
// Writing to stream
os.write(barry1);
os.close();
os.write(barray2); // this suceeds - bug
os = new FileOutputStream("abc.txt", true);
//Writing to stream
os.write(barry1);
os.close();
os.write(barray2); // crashes here, correct.
} catch (Exception e) {
e.printStackTrace();
}
}
}
Could some one help me on this, Why this behavior is different ?
While working on BufferedOutputStream found it does not throw an IOException when we wrote on it after closing the stream.
The BufferedOutputStream
code just doesn't have that sort of checking – but then neither does the FileOutputStream
. In both cases, only when the IO is actually written to disk does the OS "throw" the IOException
. It is not the Java code which is detecting that the stream has been closed. As an aside, this probably means that some native implementations don't throw at all.
The reason why the FileOutputStream
is throwing the exception on os.write(...)
, versus the BufferedOutputStream
, is that it is writing the IO to the underlying native layer immediately. If you add a os.flush()
call to the BufferedOutputStream
after the os.write()
then you will see the same exception because that forces its internal buffer to be written out.
OutputStream os = new BufferedOutputStream(new FileOutputStream("abc.txt", false));
os.write(barry1);
os.close();
os.write(barray2); // this suceeds – unfortunate behavior
os.flush(); // adding this line throws an IOException
In looking at the BufferedOutputStream
's close()
method (actually in the FilterOutputStream
base class), you can see that the output stream is not set to null
or anything:
public void close() throws IOException {
try {
flush();
} catch (IOException ignored) {
}
out.close();
}
I also don't like the fact that it is ignoring IOExceptions on close here. Wow. This tells me that we should always call flush()
by hand before close()
which is a pattern I specifically don't do.
Now compare that code to the BufferedWriter.close()
:
public void close() throws IOException {
synchronized (lock) {
if (out == null) {
return;
}
try {
flushBuffer();
} finally {
out.close();
out = null; // good doggie
cb = null;
}
}
}
BufferedWriter.close()
doesn't eat the exception and sets the delegated Writer
to be null
. Much better IMO.