我有这个方法:
private void unZipElementsTo(String inputZipFileName, String destPath) throws FileNotFoundException, IOException {
OutputStream out = null;
InputStream in = null;
ZipFile zf = null;
try {
zf = new ZipFile(inputZipFileName);
for (Enumeration<? extends ZipEntry> em = zf.entries(); em.hasMoreElements();) {
ZipEntry entry = em.nextElement();
String targetFile = destPath + FILE_SEPARATOR + entry.toString().replace("/", FILE_SEPARATOR);
File temp = new File(targetFile);
if (!temp.getParentFile().exists()) {
temp.getParentFile().mkdirs();
}
in = zf.getInputStream(entry);
out = new FileOutputStream(targetFile);
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.flush();
out.close();
in.close();
}
}
finally
{
if (out!=null) out.close();
if (zf!=null) zf.close();
if (in!=null) in.close();
}
}
对于这种方法,声纳给我这个违规:
错误做法-方法可能无法在出现异常时关闭流unZipElementsTo(String,String)可能无法在异常上关闭流
但是,我没有看到任何违规行为。也许,这只是一个假阳性?
没错。OutputStream.close()
方法本身可以引发异常。如果发生这种情况,例如在finally{}
块的第一行,则其他流将保持打开状态。
如果finally
块中的out.close()
或zf.close()
抛出异常,则不会执行其他关闭。
或者,如果您使用的是Java7或更好的版本,您可以使用新的try-with-resources机制,它可以为您处理关闭。请参阅:http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html了解有关此新机制的详细信息。
请注意,try-with-resources还可以处理打开和关闭的多个对象,并且仍然可以保证对象将按其构造的相反顺序关闭。引用同一页:
请注意,资源的close方法的调用顺序与其创建顺序相反。
为了避免在流关闭期间用异常屏蔽异常通常建议在finally中"隐藏"任何io异常。
要修复此问题,请使用org.apache.commons.io.IOUtils.closeQuietly(…)或番石榴Closeables.html#closeQuietly(java.io.Closeable)在最终关闭的中
有关异常处理问题的详细信息:
http://mestachs.wordpress.com/2012/10/10/through-the-eyes-of-sonar-exception-handling/