views:

115

answers:

5

Good afternoon all.

I have some questions about the usage of the close() method when using Java InputStreams. From what I see and read from most developers, you should always explicitly call close() on an InputStream when it is no longer needed. But, today I was looking into using a Java properties file, and every example I have found has something like this:

Properties props = new Properties();
try {
    props.load(new FileInputStream("message.properties"));
    //omitted.
} catch (Exception ex) {}

With the above example, there is now way to explicitly call close() because the InputStream is unreachable after it is used. I have seen many similar uses of InputStreams even though it seems to contradict what most people say about explicitly closing. I read through Oracle's JavaDocs and it does not mention if the Properties.load() method closes the InputStream. I am wondering if this is generally acceptable or if it is preferred to do something more like the following:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    try {
        fis.close();
    } catch (IOException ioex) {
        //omitted.
    }
}

Which way is better and/or more efficient? Or does it really matter? Thanks!

+4  A: 

It looks like the first code sample ends up relying on the finalize method in FileInputStream to actually close the file. I would say your second example is better, even though in both cases the file does get closed.

There are cases like the Byte streams where close does nothing and can be omitted, otherwise I think it's better to explicitly close the file in a finally block. If you open it, you close it.

There is a book on Oracle's site called Java Platform Performance that discusses finalizers in its appendix, it says:

You are almost always better off doing your own cleanup instead of relying on a finalizer. Using a finalizer can also leave behind critical resources that won't be recovered for an indeterminate amount of time. If you are considering using a finalizer to ensure that important resources are freed in a timely manner, you might want to reconsider.

Nathan Hughes
+9  A: 

It doesn't mention in the documentation that props.load would close the input stream. You should close the input stream manually in a finally block like you suggest.

It isn't normal for a function to close an InputStream. The same convention applies as with memory in non-garbage-collected languages: If possible, the one who opens the stream should close the stream. Otherwise, it's very easy to leave a stream open (you think a function's going to close it, but it doesn't, or something...)

Adrian Smith
+1 to "the one who opens the stream should close the stream" If that's not possible, the method comment should instruct the caller to do so. The first code example is bad practice.
leonbloy
+4  A: 

The Properties class wraps the input stream in a LineReader to read the properties file. Since you provide the input stream, it's your responsibility to close it.

The second example is a better way to handle the stream by far, don't rely on somebody else to close it for you.

One improvement you could make is to use IOUtils.closeQuietly()

http://commons.apache.org/io/api-1.2/org/apache/commons/io/IOUtils.html#closeQuietly(java.io.InputStream)

to close the stream, e.g.:

Properties props = new Properties();
InputStream fis = new FileInputStream("message.properties");
try {
    props.load(fis);
    //omitted.
} catch (Exception ex) {
    //omitted.
} finally {
    IOUtils.closeQuietly(fis);
}
Jon
+1 for the `closeQuietly`.
uckelman
+2  A: 

The examples in the Properties Tutorial close the FileInputStream explicitly after loading, so I think it's safe to assume that the load method isn't responsible for it, you are.

// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();

Just for reference, I checked the Apache Harmony implementation of Properties, and it does not close the stream on load.

Bill the Lizard
@Bill, the Properties tutorial is the explanation I was hoping for. Thanks for the link!
Jason Watkins