java try finally block to close stream

41,507

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.

Share:
41,507
jhlu87
Author by

jhlu87

Trader learning to program

Updated on July 11, 2022

Comments

  • jhlu87
    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 another try block in my finally 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
    Jord Sonneveld over 12 years
    To whomever down-voted my answer, could you please explain why so that I can learn from it?
  • Akshay
    Akshay about 8 years
    I went with the second approach since its more cleaner and readable. This is really important as we want to avoid any memory leaks.
  • thaspius
    thaspius over 6 years
    I'll upvote you so it balances out. Guava is a great library
  • surendrapanday
    surendrapanday about 5 years
    printing problem in stack-trace without logging it in is a problem, so instead that I suggest people to use log.debug(readException.getMessage());
  • Sebastian
    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.