I have three questions.
To explain, I was reviewing someone\'s code, and noticed BufferedReader
s sometimes aren\'t being closed. Usually, Eclipse gives a w
I would say that since they're creating a BufferedReader
around a given InputStream
, the code is safe not calling close()
. The code that calls close()
should always be the code that creates the stream and done using try/finally.
public static void read(String str) throws IOException {
FileInputStream stream = null
try {
stream = new FileInputStream(str);
readStreamToConsole(stream);
} finally {
if (stream != null)
stream.close();
}
}
private static void readStreamToConsole(InputStream stream) {
BufferedReader stdOut = new BufferedReader(new InputStreamReader(stream));
String output = null;
while ((output = stdOut.readLine()) != null)
System.out.println(output);
}
Another note: your code appears to be logging output from some other process. You probably wouldn't be able to close the stream anyway. Without testing it myself, I'm not sure what would happen if you closed a stream from another process.
Oh, and the IOException
isn't likely to happen because the stream is coming from another process. That's not likely to happen unless some irrecoverable error occurs. It still wouldn't be a bad idea to log the exception somehow, though.
Edit to address your comment about mixed answers:
Let's use an output stream and BufferedWriter as an example this time:
private static final String NEWLINE = System.getProperty("line.separator");
public static void main(String[] args) throws IOException {
String file = "foo/bar.txt";
FileOutputStream stream = null;
try {
stream = new FileOutputStream(file);
writeLine(stream, "Line 1");
writeLine(stream, "Line 2");
} finally {
if (stream != null)
stream.close();
}
}
private static void writeLine(OutputStream stream, String line) throws IOException {
BufferedWriter writer = new BufferedWriter(new InputStreamWriter(stream));
writer.write(line + NEWLINE);
}
This works. The writeLine method is used as a delegate to creating writer
and actually writing a single line
to the file. Of course, this logic could be something more complex, such as turning an object into a String
and writing it. This makes the main
method a little easier to read too.
Now, what if instead, we closed the BufferedWriter?
private static void writeLine(OutputStream stream, String line) throws IOException {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new InputStreamWriter(stream));
writer.write(line + NEWLINE);
} finally {
if (writer != null)
writer.close();
}
}
Try running it with that, and it will fail every time on the second writeLine
call. It's good practice to always close streams where they're created, instead of where they're passed. It may be fine initially, but then trying to change that code later could result in errors. If I started with only 1 writeLine
call with the bad method and someone else wanted to add a second one, they'd have to refactor the code so that writeLine
didn't close the stream anyway. Getting close-happy can cause headaches down the road.
Also note that technically, the BufferedWriter
isn't the actual handle to your system resource, the FileOutputStream
is, so you should be closing on the actual resource anyway.
So, rule of thumb: only close your streams where you create them, and always do the creation and closing in a try/finally block (or Java 7's awesome try/resource block, which does the closing for you).