Monday, December 28, 2009

Using Closeable Interface


static void copy(String src, String dest) throws IOException {
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buf = new byte[1024];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
if (in != null) in.close();
if (out != null) out.close();
}
}



The stream fields (in and out) are initialized to null and set to the new streams as soon as they are created. The finally block closes the stream referred to by each field if it is non-null. An error during the copy would cause an IOException, but the finally block would still execute before the method returns. What could go wrong?

Yes...
The problem resides in finally block
The close method can throw an IOException too. If this happens when in.close is called, the exception prevents out.close from getting called, and the output stream remains open.

The solution would be to wrap each call to close in a nested try block

} finally {

if (in != null) {

try {

in.close();

} catch (IOException ex) {

// There is nothing we can do if close fails

}

}



if (out != null) {

try {

out.close();

} catch (IOException ex) {

// Again, there is nothing we can do if close fails

}

}

}



Closeable interface comes to your rescue, helping you to abstract it at one routine
like this


} finally {

closeIgnoringException(in);

closeIgnoringException(out);

}



private static void closeIgnoringException(Closeable c) {

if (c != null) {

try {

c.close();

} catch (IOException ex) {

// ignore if you dont have any thing to do here
}

}

}


And finally

A Closeable is a source or destination of data that can be closed. The close method is invoked to release resources that the object is holding.

No comments: