Granny's Programming Pearls
"inside of every large program is a small program struggling to get out"
JavaRanch.com/granny.jsp
The moose likes Beginning Java and the fly likes Closing input and output streams Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "Closing input and output streams" Watch "Closing input and output streams" New topic
Author

Closing input and output streams

Ken Austin
Ranch Hand

Joined: Aug 20, 2012
Posts: 39

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

Joined: Oct 13, 2005
Posts: 38480
    
  23
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

Joined: Jan 28, 2003
Posts: 4181
    
  21

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.


Steve
Campbell Ritchie
Sheriff

Joined: Oct 13, 2005
Posts: 38480
    
  23
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

Joined: Jan 28, 2003
Posts: 4181
    
  21

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

Joined: Aug 20, 2012
Posts: 39

Thanks, Campbell. That helps. I appreciate the reply.
Mike Simmons
Ranch Hand

Joined: Mar 05, 2008
Posts: 3012
    
  10
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

Joined: Mar 05, 2008
Posts: 3012
    
  10
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)
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Closing input and output streams