Consider :
public static void read(String filename) throws IOException {
String charsetName = "UTF-8";
InputStream file = new FileInputStream(filename); // say no problem
InputStreamReader reader = new InputStreamReader(file, charsetName);
BufferedReader buffer = new BufferedReader(reader);
try {
buffer.readLine();
} finally {
try {
buffer.close();
} catch (IOException e) {
// report at least
e.printStackTrace();
}
}
}
If new InputStreamReader(file, charsetName)
throws UnsupportedEncodingException
, the buffer.close();
line will never be called. The alternative is extra verbose :
InputStream file = new FileInputStream(filename);
try {
InputStreamReader reader = new InputStreamReader(file);
try {
BufferedReader buffer = new BufferedReader(buffer);
try {
buffer.readLine();
} finally {
buffer.close(); // should catch
}
} finally {
reader.close(); // should catch
}
} finally {
file.close(); // should catch
}
and it needlessly closes all streams (while output.close();
should suffice - actually any of them should suffice if successful - see comments in the code by Skeet).
Wrapping the constructors
BufferedReader buffer = new BufferedReader(
new InputStreamReader(new FileInputStream(filename), charsetName));
is essentially just hiding the problem.
Notice I use the try-finally idiom suggested by @TomHawtin-tackline here for instance - but the more common approach :
public static void read(String filename) throws IOException {
String charsetName = "UTF-8";
InputStream file = null;
InputStreamReader reader = null;
BufferedReader buffer = null;
try {
file = new FileInputStream(filename);
reader = new InputStreamReader(file, charsetName);
buffer = new BufferedReader(reader);
buffer.readLine();
} finally {
try {
if(buffer != null) buffer.close();
} catch (IOException e) {
// report at least
e.printStackTrace();
}
// Rinse and repeat for the rest
}
}
is as awkward.
Question :
How would you handle this case ?
Would :
public static void read(String filename) throws IOException {
String charsetName = "UTF-8";
InputStream file = new FileInputStream(filename);
try {
InputStreamReader reader = new InputStreamReader(file, charsetName);
BufferedReader buffer = new BufferedReader(reader); // Eclipse warning
buffer.readLine();
// notice that if these were out put streams we SHOULD FLUSH HERE
} finally {
try {
file.close();
} catch (IOException e) {
// report at least
e.printStackTrace();
}
}
}
do ? In other words closing the innermost stream (contrary to what is usually asked) would be the cleanest solution when there are more than 2 wrapped streams ? Are there cases when finally
the decorator should be also closed() ? See for instance points here. Notice that Eclipse warns :
Resource leak: 'buffer' is never closed
Is Eclipse right ?
This is Java 6 - Android is Java 6 only I remind you. Trying to factor out IO code in some utility classes, once and for all
if(buffer != null) buffer.close();
..right? – Breadth