Is there a not so ugly way of treat the close()
exception to close both streams then:
InputStream in = new FileInputStream(inputFileName);
In C#, there is using
construction that closes closable objects automatically, when we leave the scope:
using(Stream s = new Stream(filename)) {
s.read();
}
I think that this is a short form for java's try-finally block. Java 6 has introduced the Closable interface. So, using
is almost there. When the final step is done in Java 7, it will be terrific indeed.
Since Java 7 there is a much nicer way to write try-finally block in regards to Closeable
resources.
Now you can create your resources in parenthesis after the try
keyword, like this:
try (initialize resources here) {
...
}
And they will be closed automatically after the block of code is finished. There is no need for the finally
part.
An example:
try (
ZipFile zf = new ZipFile(zipFileName);
BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset);
) {
// Enumerate each entry
for (Enumeration entries = zf.entries(); entries.hasMoreElements();) {
// Get the entry name and write it to the output file
String newLine = System.getProperty("line.separator");
String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
writer.write(zipEntryName, 0, zipEntryName.length());
}
}
And after the for
loop is done, the resources will be closed!
In most cases the 'in' close() exception is irrelevant, so:
try {
copy(in, out);
} finally {
try { in.close() } catch (Exception e) { /* perhaps log it */ }
try { out.close() } catch (Exception e) {/* perhaps log it */ }
}
It's usually bad practice to swallow exceptions, but in this case I think it's ok.
I strongly believe that in Java 7.0, you do not need to explicitly close the stream yourself anymore. Language Features in Java 7
try (BufferedReader br = new BufferedReader(new FileReader(path)) {
return br.readLine();
}
try {
final InputStream in = new FileInputStream(inputFileName);
try {
final OutputStream out = new FileOutputStream(outputFileName);
try {
copy(in, out);
out.flush(); // Doesn't actually do anything in this specific case.
} finally {
out.close();
}
} finally {
in.close();
}
} catch (IOException exc) {
throw new SomeRelevantException(exc);
}
Remember that opening a stream may throw an exception, so you do need a try
between the stream openings (please don't do some hack involving null
s. Anything can throw an Error
(which are not an instances of Exception
).
It turns out that catch
and finally
should rarely share the same try
.
Since Java SE 7 you can write use try-with-resource to avoid so much indentation. It more or less does the same thing although there are suppressed exception hidden away.
try (
final InputStream in = new FileInputStream(inputFileName);
final OutputStream out = new FileOutputStream(outputFileName);
) {
copy(in, out);
out.flush(); // Doesn't actually do anything in this specific case.
} catch (IOException exc) {
throw new SomeRelevantException(exc);
}
You may want to use the Execute Around idiom.
I believe the standard good way to copy is using NIO's transferTo
/transferFrom
.
Use
IOUtils.closeNoThrow(myInputStream);
Simple and elegant.