'的FileInputStream'退出时没有关闭。

时间:2014-11-26 09:27:09

标签: java klocwork

我已经对我的代码执行了klocwork代码分析。 我收到以下错误 我终于关闭了inputream 即使这样,我也会收到错误 '的FileInputStream'退出时没有关闭。

以下是一段代码

    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();
                }
            }
        }
    }

1 个答案:

答案 0 :(得分:1)

这很微妙,但如果仔细查看finally块,您会看到如果关闭zipInputStream,则fileInputStreamfileOutputStream永远不会关闭。关闭fileInputStream的异常将阻止fileOutputStream被关闭。即使您的try中包含fileInputStream.close(),也可能无法访问(因为主代码中存在例外情况)。

} finally {
    try {
        // close last ZipEntry
        if (zipInputStream != null) {
            zipInputStream.closeEntry();    // An exception here...
            zipInputStream.close();         // Or here...
        }                                   // Prevents all of the following from running
        if (fileInputStream != null) {
            fileInputStream.close();        // Similarly, an exception here...
        }
        if (fileOutputStream != null) {     // Prevents this from running
            fileOutputStream.close();
        }
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

我建议使用新的try-with-resources声明。


你在下面问过:

  

是不是可以使用简单的尝试?因为我正在使用java 6.Its要求

首先,无论是谁给了你改变它的要求。或许将它们交给多年历,并指向2011年7月28日 - 三年半前 - 这是Java 7被Java 7取代的日期,然后是2014年3月18日Java 8取代Java 7的时候。至少使用Java 7已经过去了,Java 7有try-with-resources

但是,是的,当然可以在Java 1和Java 7之间的15年内处理这个问题。您只需要单独处理关闭异常而不是作为一个组。我曾经在StreamHelper类中使用辅助函数。它们看起来像这样:

public static InputStream cleanClose(InputStream in ) {
    if (in != null) {
        try {
            in.close();
        }
        catch (Exception e) {
            // ...do something appropriate, but swallow it...
        }
    }
    return null;
}

......同样适用于OutputStream等。

然后我会在异常处理程序中使用它,使用这种模式:

InputStream theInput = null;
OutputStream theOutput = null;
try {
    theInput = new FileInputStream(/*...*/);
    theOutput = new FileOutputStream(/*...*/);

    // ...do something with the streams

    // Close them normally
    theOutput.close();
    theOutput = null;
    theInput.close();
    theInput = null;
}
finally {
    // Ensure they're closed
    theOutput = StreamHelper.cleanClose(theOutput);
    theInput = StreamHelper.cleanClose(theInput);
}

除此之外,这让我在详细方法上声明异常并允许它们传播,同时仍然在detail方法中处理本地流。

但是,

try-with-resources更好,因为在清理期间发生的异常同时引发另一个异常成为引发的主要异常的一部分(它们被称为“被抑制”异常,它们位于主要异常上),对于像上面这样的旧式代码,你依靠日志记录或你自己的定制机制来了解它们。