0

我已经对我的代码进行了 klocwork 代码分析。我收到以下错误我最终关闭了输入流即使这样我也收到错误'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();
                }
            }
        }
    }
4

1 回答 1

1

这很微妙,但如果你仔细观察你的finally块,你会发现如果有异常关闭zipInputStreamfileInputStream并且fileOutputStream永远不会关闭。异常关闭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 6 被 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);
}

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

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

于 2014-11-26T09:32:13.990 回答