Closing inputstreams in Java

前端 未结 6 1072
眼角桃花
眼角桃花 2020-12-03 13:19

I have the following piece of code in a try/catch block

 InputStream inputstream = conn.getInputStream();
 InputStreamReader inputstreamreader = new  InputSt         


        
6条回答
  •  醉梦人生
    2020-12-03 14:20

    Normally it is ok to just close the most outer stream, because by convention it must trigger close on the underlying streams.

    So normally code looks like this:

    BufferedReader in = null;
    
    try {
        in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        ...
        in.close(); // when you care about Exception-Handling in case when closing fails
    }
    finally {
        IOUtils.closeQuietly(in); // ensure closing; Apache Commons IO
    }
    

    Nevertheless there may be rare cases where an underlying stream constructor raises an exception where the stream is already opened. In that case the above code won't close the underlying stream because the outer constructor was never called and in is null. So the finally block does not close anything leaving the underlying stream opened.

    Since Java 7 you can do this:

        try (OutputStream out1 = new ...; OutputStream out2 = new ...) {
            ...
            out1.close(); //if you want Exceptions-Handling; otherwise skip this
            out2.close(); //if you want Exceptions-Handling; otherwise skip this            
        } // out1 and out2 are auto-closed when leaving this block
    

    In most cases you do not want Exception-Handling when raised while closing so skip these explicit close() calls.

    Edit Here's some code for the non-believers where it is substantial to use this pattern. You may also like to read Apache Commons IOUtils javadoc about closeQuietly() method.

        OutputStream out1 = null;
        OutputStream out2 = null;
    
        try {
            out1 = new ...;
            out2 = new ...;
    
            ...
    
            out1.close(); // can be skipped if we do not care about exception-handling while closing
            out2.close(); // can be skipped if we ...
        }
        finally {
            /*
             * I've some custom methods in my projects overloading these
             * closeQuietly() methods with a 2nd param taking a logger instance, 
             * because usually I do not want to react on Exceptions during close 
             * but want to see it in the logs when it happened.
             */
            IOUtils.closeQuietly(out1);
            IOUtils.closeQuietly(out2);
        }
    

    Using @Tom's "advice" will leave out1 opened when creation of out2 raises an exception. This advice is from someone talking about It's a continual source of errors for obvious reasons. Well, I may be blind, but it's not obvious to me. My pattern is idiot-safe in every use-case I can think of while Tom's pattern is error-prone.

提交回复
热议问题