Win a copy of Functional Reactive Programming this week in the Other Languages forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Closing input and output streams

 
Ken Austin
Ranch Hand
Posts: 39
Chrome Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Greetings, fellow ranchers. I hope everyone had a great holiday season.

The textbook I'm using said it's always a good idea to make sure that the input streams and output streams get closed when you're done with them. In the excerpt below, the author closes the streams in the try clause. Would it be better to put them after the try..catch statement? Or in a finally clause?

 
Campbell Ritchie
Sheriff
Pie
Posts: 50258
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No choice.
If you are using Java1-6, use a finally.
If you are using Java7, try-with-resources.
You can see an example of finally here, and a better example if you scroll down that last link.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbel, any reason you don't do this:

Moving the second try/catch into the finally clause prevents the close() exception from hiding the exception in the main try{} block, which is generally more important. I don't recall but I think the try-with-resources behaves like this.
 
Campbell Ritchie
Sheriff
Pie
Posts: 50258
79
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes.
The BufferedReader constructor and the FileReader constructor both declare checked Exceptions, so those calls must be inside the try. If you don’t declare those references (or at least the BufferedReader) before the try, they will be out of scope in the finally. So you have to initialise them to something and null initialisation is the only way to avoid those Exceptions. Then you could suffer a NullPointerException in the finally if you don’t use a nullity test.
 
Steve Luke
Bartender
Posts: 4181
22
IntelliJ IDE Java Python
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fair enough, I hadn't looked at the opening side of the code. I was focusing more on the closing/finally part, with the try{close}catch{ignore-or-not} construct. Any thoughts on that? Assuming you change the initialization the way you suggest and add a null check before the close?
 
Ken Austin
Ranch Hand
Posts: 39
Chrome Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks, Campbell. That helps. I appreciate the reply.
 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There are still other things that can go wrong though. If it's an output stream, then close() includes a final flush() of data (e.g. if there's a buffered stream involved along the way) and this may incur a new exception that should not be swallowed, unless another exception has already been thrown.


I have deliberately not included a try/catch for the IOException above, because I don't want to propagate the myth that catching such an exception is the only thing to do. It can be perfectly reasonable to simply declare that your method throws IOException, and let it be caught at a higher level. But if you want to catch and log it locally that can be done. First let's create a utility method:

And then:


Clearly, if you're using Java 7, it's much, much easier to just use try-with-resources:

 
Mike Simmons
Ranch Hand
Posts: 3090
14
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Oh, I see Google Guava has a utility almost the same as the method I suggested, except the meaning of the boolean is reversed. And their logging uses java.util.Logger, so if you want to log using another framework, you may need to roll you own. Otherwise, use Closeables.close(Closeable closeable, boolean swallowIOException)
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic