Java IO: Exception Handling
Jakob Jenkov |
Streams and Readers / Writers need to be closed properly when you are done using them. This is done
by calling the close()
method. This requires a little thought though. Look at this code:
InputStream input = new FileInputStream("c:\\data\\input-text.txt"); int data = input.read(); while(data != -1) { //do something with data... doSomethingWithData(data); data = input.read(); } input.close();
This piece of code looks okay at first glance. But what happens if an exception is thrown from inside
the doSomethingWithData()
method? That's right! The InputStream
is never closed!
To avoid this you can rewrite the code to this:
InputStream input = null; try{ input = new FileInputStream("c:\\data\\input-text.txt"); int data = input.read(); while(data != -1) { //do something with data... doSomethingWithData(data); data = input.read(); } }catch(IOException e){ //do something with e... log, perhaps rethrow etc. } finally { if(input != null) input.close(); }
Notice how the InputStream
is now closed inside a finally clause. No matter what happens
inside the try-block, the finally clause will be executed. Hence the InputStream
will always
be closed.
But what happens if close()
throws an exception? Say the stream was already closed? Well, to
catch that situation you will have to wrap the call to close()
in a try-catch block too, like
this:
} finally { try{ if(input != null) input.close(); } catch(IOException e){ //do something, or ignore. } }
The code to properly handle the iteration of an InputStream
(or OutputStream for that matter),
can bet quite ugly as you can see, once you get the correct exception handling in there too. This
ugly exception handling code isn't particularly nice to have spread throughout your code, repeated again
and again. What if someone who is in a hurry cuts a corner and skips the exception handling?
Furthermore, imagine that an exception is thrown first from doSomethingWithData()
. The first
catch
clause will catch that exception and the finally clause will then try to close the
InputStream
. But, what happens if an exception is also thrown from the input.close()
method? Which of the two exceptions should be propagated up the call stack?
Luckily, there is a way around this problem. The solutions is called "Exception Handling Templates". Create an exception handling template that properly closes your stream after use. This template is written once, and reused throughout your code. Nice and simple. You learn more, go to Exception Handling Templates in Java.
Java IO Exception Handling From Java 7
From Java 7 on and forward Java contains a new exception handling mechanism called "try with resources". This
exception handling mechanism is especially targeted at handling exception handling when you are using resources
that need to be closed properly after use, like InputStream
, OutputStream
etc.
You can read more about it in my tutorial about Try With Resources in Java 7.
Tweet | |
Jakob Jenkov |