I have performed klocwork code analysis on my code. I am getting the following error I have closed the inputsream in finally Even then i am getting the error 'fileInputStream' is not closed on exit.
Following is the piece of code
LOGGER.log(Level.INFO, "Inside unzipDownloadedFile method");
File fileDirectory = new File(destDir);
FileInputStream fileInputStream = null;
// buffer for read and write data to file
byte[] buffer = new byte[1024];
ZipInputStream zipInputStream = null;
File zipPath = new File(zipFilePath);
FileOutputStream fileOutputStream = null;
// create output directory if it doesn't exist
if (!fileDirectory.exists()) {
fileDirectory.mkdirs();
}
if (zipPath != null) {
if (zipPath.exists()) {
try {
fileInputStream = new FileInputStream(zipFilePath);
zipInputStream = new ZipInputStream(fileInputStream);
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
String fileName = zipEntry.getName();
File newFile = new File(destDir + File.separator
+ fileName);
// create directories for sub directories in zip
new File(newFile.getParent()).mkdirs();
fileOutputStream = new FileOutputStream(newFile);
int zipStream = 0;
while ((zipStream = zipInputStream.read(buffer)) > 0) {
fileOutputStream.write(buffer, 0, zipStream);
}
fileOutputStream.close();
// close this ZipEntry
zipInputStream.closeEntry();
zipEntry = zipInputStream.getNextEntry();
}
fileInputStream.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} finally {
try {
// close last ZipEntry
if (zipInputStream != null) {
zipInputStream.closeEntry();
zipInputStream.close();
}
if (fileInputStream != null) {
fileInputStream.close();
}
if (fileOutputStream != null) {
fileOutputStream.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
It's subtle, but if you look closely at your
finally
block, you'll see that if there's an exception closingzipInputStream
,fileInputStream
andfileOutputStream
are never closed. And an exception closingfileInputStream
will preventfileOutputStream
from being closed. And even though yourtry
has afileInputStream.close()
in it, it may not be reached (because of an exception in the main code).I'd suggest using the new
try-with-resources
statement.You've asked below:
First off, get whoever it is who gave you that requirement to change it. Perhaps hand them a multi-year calendar and point to July 28th, 2011 — three and a half years ago — which is the date Java 6 was replaced by Java 7, then again at March 18, 2014, when Java 8 replaced Java 7. It's well past time to at least be using Java 7, and Java 7 has
try-with-resources
.But yes, of course it was possible to handle this in the 15 years between Java 1 and Java 7 . You just have to handle the close exceptions individually rather than as a group. I used to have helper functions for this in a
StreamHelper
class. They looked like this:...and similarly for
OutputStream
and such.Then I'd use it in exception handlers, using this pattern:
Among other things, this let me declare exceptions on detail methods and allow them to propagate, while still handling local streams within the detail method.
try-with-resources
is better, though, because exceptions that occur during cleanup while another exception is being raised become part of the main exception being raised (they're called "suppressed" exceptions and they're on the main exception), whereas with old-style code like the above, you rely on logging or your own bespoke mechanism for knowing about them.