best practices for handling I/O

As part of my error handling project, I’ve been cleaning up problems with
file I/O wherever I see it. Two common problems I’ve noticed are that we
often don’t explicitly close InputStreams, OutputStreams, Readers, and
Writers, and that when we do close them, we do it in such a way that we
might miss the close (or another exception) due to an exception during
I/O.

For situations where we want handle the IOException right here, this is
the best way I’ve come up with:

InputStream in = null;
try {
  // ... read some stuff ...
  in.close();
}
catch (IOException e) {
  // ... handle the error ...
}
finally {
  IOUtils.closeQuietly(in);
}

IOUtils.closeQuietly(in) calls in.close() if in is nonnull, and simply logs
the exception if in.close() throws.

The important change here from what I’d been doing before is that there’s
now an attempt to close within the try block, whereas before we only
attempted to close within a finally block. A failure to close can be rather
problematic with OutputStreams and Writers, since in those cases close() is
calling flush() for us, and without that data could be lost. Hence, we need
to warn the user when close() fails, and the most straightforward way to do
that is to have the close() inside the try block—that way, if close()
throws, the IOException will be handled properly. Secondly, we need to have
a close() in the finally block, since without that, a stream which had an
IOException before the close() in the try block won’t be closed at all.

In the situation where you’re throwing an IOException upwards, just omit
the catch block in the above example.

Does the make sense to everybody?

Sounds good. That’s what I have been trying to do. Strangely, I found I couldn’t call IOUtils.closeQuietly(in) on one of the types of Stream/Readers I was using because it didn’t implement Closeable. Can’t remember what ir was now.

B.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake “Brent Easton”:

It couldn’t have been anything which implements InputStream, OutputStream,
Reader, or Writer, since all of those interfaces implement Closeable.

I’ve added closeQuietly(ImageInputStream), closeQuietly(ZipFile),
closeQuietly(Socket), and closeQuietly(ServerSocket) fairly recently,
because none of those implement Closeable (though arguably they all
should).

(Oddly, ImageInputStream is not an InputStream—that might have been
the one which bit you.)


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

Thus spake Joel Uckelman:

BTW, if you find something which seems like it should be a Closeable
but isn’t, add an IOUtils.closeQuietly() for it.


J.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)

It was a ZipFile.

B.


Messages mailing list
Messages@forums.vassalengine.org
forums.vassalengine.org/mailman/ … engine.org

Post generated using Mail2Forum (mail2forum.com)