Java IO: Exception Handling

Jakob Jenkov
Last update: 2014-10-18

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.

Jakob Jenkov

Featured Videos

Java Generics

Java ForkJoinPool

P2P Networks Introduction



















Close TOC
All Tutorial Trails
All Trails
Table of contents (TOC) for this tutorial trail
Trail TOC
Table of contents (TOC) for this tutorial
Page TOC
Previous tutorial in this tutorial trail
Previous
Next tutorial in this tutorial trail
Next