问题 关闭ZipOutputStream


我有点困惑。我知道空拉链不合法。但是这个示例片段呢:

ZipOutputStream zos = null; 
try
{
    zos = new ZipOutputStream(new FileOutputStream("..."));
    //
    //..
    //
}
finally
{
    zos.close();
}

如果由于某种原因(可能是异常情况)没有添加任何zip条目,则在紧密尝试时将抛出以下异常:

Exception in thread "main" java.util.zip.ZipException: ZIP file must have at least one entry
    at java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:304)
    at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:146)
    at java.util.zip.ZipOutputStream.close(ZipOutputStream.java:321)

在这种情况下,关闭流的最简洁方法是什么?

谢谢...


9704
2018-01-13 15:01


起源



答案:


你应该关闭 FileOutputStream不是 ZipOutputStream,因为前者实际上是消耗系统资源的。

File zipFile = new File("/tmp/example.zip");
FileOutputStream fos = null;
try
{
   fos = new FileOutputStream(zipFile);
   ZipOutputStream zos = new ZipOutputStream(fos);

   // ...

   zos.close();
}
catch (IOException ex)
{
   // log/report exception, then delete the invalid file
   IOUtils.closeQuietly(fos);
   zipFile.delete();
}
finally
{
   IOUtils.closeQuietly(fos);
}

IOUtils 上课是在 Jakarta Commons IO。使用它意味着您不必处理可能但很少有用的问题 IOException 可以抛出的 close()


7
2018-01-13 15:14



谢谢你的帮助,这应该是事实:-) - Lachezar Balev
@lucho - 刚刚编辑了这个例子,使其更加健壮。 - Anon
这个解决方案很好,但推理不正确:您可以关闭任一流。关闭ZipOutputStream之类的包装器流也将关闭较低级别的FileOutputStream。 - Daniel Winterstein
请注意,Java 7引入了一个 尝试与 - 资源 使这种代码更清洁的块! - Renato


答案:


你应该关闭 FileOutputStream不是 ZipOutputStream,因为前者实际上是消耗系统资源的。

File zipFile = new File("/tmp/example.zip");
FileOutputStream fos = null;
try
{
   fos = new FileOutputStream(zipFile);
   ZipOutputStream zos = new ZipOutputStream(fos);

   // ...

   zos.close();
}
catch (IOException ex)
{
   // log/report exception, then delete the invalid file
   IOUtils.closeQuietly(fos);
   zipFile.delete();
}
finally
{
   IOUtils.closeQuietly(fos);
}

IOUtils 上课是在 Jakarta Commons IO。使用它意味着您不必处理可能但很少有用的问题 IOException 可以抛出的 close()


7
2018-01-13 15:14



谢谢你的帮助,这应该是事实:-) - Lachezar Balev
@lucho - 刚刚编辑了这个例子,使其更加健壮。 - Anon
这个解决方案很好,但推理不正确:您可以关闭任一流。关闭ZipOutputStream之类的包装器流也将关闭较低级别的FileOutputStream。 - Daniel Winterstein
请注意,Java 7引入了一个 尝试与 - 资源 使这种代码更清洁的块! - Renato


您应该跟踪是否添加了zip流的内容并仅在添加内容时将其关闭:

ZipOutputStream zos = null; 
OutputStream file = new FileOutputStream("...")
int itemsAdded=0;
try
{
    zos = new ZipOutputStream(file);
    //
    //..
    // itemsAdded++; 
}
finally
{
    if ( itemsAdded > 0 ) {
         zos.close();
    } else {
         file.close();
    }
}

如果你不需要计数只需使用一个 boolean 旗。


3
2018-01-13 15:08



zip文件保持打开状态并锁定...如何关闭它? - Lachezar Balev
当zip流为空时,@ lucho添加了一些代码来关闭文件。看一看。 - Mihai Toader


不是在添加内容时关闭流,而是在运行邮政编码之前进行条件检查以查看是否有任何要压缩的内容。这有助于我简化流程,我认为可以用来处理“ZIP文件必须至少有一个条目”的问题。是的,关闭 zos 可能会抛出其他异常,但这种情况很少见。

我认为这是Java的问题,当没有要压缩的文件时,它无法处理。

即:

int itemsToAdd=0;
//....

if ( itemsToAdd > 0 ) {

    ZipOutputStream zos = new ZipOutputStream(file);
    try {
        //add files to zip
    }
    finally {
        zos.close();
    }
}

3
2018-05-17 03:13