Closing Java InputStreams
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 no 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?
Solution 1:
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()
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);
}
Solution 2:
I would go with a try-with-resources (at least for Java 7+):
Properties props = new Properties();
try(InputStream fis = new FileInputStream("message.properties")) {
props.load(fis);
//omitted.
} catch (Exception ex) {
//omitted.
}
The close()
call should be automatically called when the try block is exited.
Solution 3:
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.
Solution 4:
If you're using Java 7+ you can use this:
try(InputStream is = new FileInputStream("message.properties")) {
// ...
}
Solution 5:
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...)