java try finally block to close stream
Solution 1
It seems a bit clunky.
It is. At least java7's try with resources fixes that.
Pre java7 you can make a closeStream
function that swallows it:
public void closeStream(Closeable s){
try{
if(s!=null)s.close();
}catch(IOException e){
//Log or rethrow as unchecked (like RuntimException) ;)
}
}
Or put the try...finally inside the try catch:
try{
BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()));
try{
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
}finally{
r.close();
}
}catch(IOException e){
e.printStackTrace();
}
It's more verbose and an exception in the finally will hide one in the try but it's semantically closer to the try-with-resources introduced in Java 7.
Solution 2
Also if you're using Java 7, you can use a try-with-resources statement:
try(BufferedReader r = new BufferedReader(new InputStreamReader(address.openStream()))) {
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException readException) {
readException.printStackTrace();
}
Solution 3
In Java 7 you can do this...
try (BufferedReader r = new BufferedReader(...)){
String inLine;
while ((inLine = r.readLine()) != null) {
System.out.println(inLine);
}
} catch(IOException e) {
//handle exception
}
- Declaring a variable in the try block requires that it implements
AutoCloseable
. - Declaring a variable in the try block also limits its scope to the try block.
- Any variable declared in the try block will automatically have
close()
called when the try block exits.
It's called a Try with resources statement.
Solution 4
Yes it is clunky, ugly and confusing. One possible solution is to use Commons IO which offers a closeQuietly method.
There's a number of questions in the "Related" column on the right hand of this page that are actually duplicates, I advise to look through these for some other ways of dealing with this issue.
Solution 5
Like the answer mentioning the Commons IO library, the Google Guava Libraries has a similar helper method for things which are java.io.Closeable. The class is com.google.common.io.Closeables. The function you are looking for is similarly named as Commons IO: closeQuietly().
Or you could roll your own to close a bunch like this: Closeables.close(closeable1, closeable2, closeable3, ...) :
import java.io.Closeable;
import java.util.HashMap;
import java.util.Map;
public class Closeables {
public Map<Closeable, Exception> close(Closeable... closeables) {
HashMap<Closeable, Exception> exceptions = null;
for (Closeable closeable : closeables) {
try {
if(closeable != null) closeable.close();
} catch (Exception e) {
if (exceptions == null) {
exceptions = new HashMap<Closeable, Exception>();
}
exceptions.put(closeable, e);
}
}
return exceptions;
}
}
And that even returns a map of any exceptions that were thrown or null if none were.
Comments
-
jhlu87 almost 2 years
I want to close my stream in the finally block, but it throws an
IOException
so it seems like I have to nest anothertry
block in myfinally
block in order to close the stream. Is that the right way to do it? It seems a bit clunky.Here's the code:
public void read() { try { r = new BufferedReader(new InputStreamReader(address.openStream())); String inLine; while ((inLine = r.readLine()) != null) { System.out.println(inLine); } } catch (IOException readException) { readException.printStackTrace(); } finally { try { if (r!=null) r.close(); } catch (Exception e){ e.printStackTrace(); } } }
-
Jord Sonneveld over 12 yearsTo whomever down-voted my answer, could you please explain why so that I can learn from it?
-
Akshay about 8 yearsI went with the second approach since its more cleaner and readable. This is really important as we want to avoid any memory leaks.
-
thaspius over 6 yearsI'll upvote you so it balances out. Guava is a great library
-
surendrapanday about 5 yearsprinting problem in stack-trace without logging it in is a problem, so instead that I suggest people to use
log.debug(readException.getMessage());
-
Sebastian about 4 years@surendrapanday I don't see why that should be a problem. Logging paradigms has changed since 12 factors so logging to standard output is no more an issue. You log everything to stdout as you treat your process like a pipe and you can process your logs the way you want without touching your code.