What is the correct way to silently close InputStream in finally block without losing the original exception?

Best way is to use Java 7 and use try with resources, or do same thing manualy and add exception from closing as suppressed exception.

Pre Java 7: If you are throwing your custom exception, you can add in it supressed exception like it is done in Java 7 (in your exception create fields List suppressed and put there exceptions from close operation and when dealing with your exception, look there too. If you cannot do that, I don't know anything better than just log it.

examples: from Java tutorials

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

but better form is:

static String readFirstLineFromFile(String path) throws IOException {
    try (FileReader fr = new FileReader(path);
         BufferedReader br = new BufferedReader(fr)) {
        return br.readLine();
    }
}

This way even if creation of FileReader is succesfull but creation of BufferedReader fails (eg not enough memory), FileReader will be closed.


You can close it with IOUtils from https://commons.apache.org/proper/commons-io/

public void readStream(InputStream ins) {
    try {
        //do some operation with stream         
    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        IOUtils.closeQuietly(ins);
    }
}

The Java 6 specs say

If execution of the try block completes abruptly for any other reason R, then the finally block is executed. Then there is a choice: If the finally block completes normally, then the try statement completes abruptly for reason R. If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and reason R is discarded).

So you are right, you will lose the original exception.

The solution probably is to write your finally block so defensively that it is a bigger surprise (worth propagating) if the finally block fails than if an exception comes out of the try catch block.

So, for example, if it is possible that the stream may be null when you try to close it, check it:

InputStream is = new FileInputStream("test");
try {
    for(;;) {
        int b = is.read();
        ...
    }
} finally {
    try {
        if( is!=null ) {
            is.close();
        }
    } catch(IOException e) {
    }
}

In Java 7, Alpedar's solution is the way to go of course.

Tags:

Java