关闭 ZipOutputStream

发布于 2024-10-11 12:54:41 字数 647 浏览 4 评论 0原文

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

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)

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

谢谢...

I'm a bit confused. I know that an empty zip is not legal. But what about this sample snippet:

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

If no zip entries had been added for some reason (possibly exceptional situation) then the following exception will be thrown on close attempt:

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)

In this situation what would be the cleanest way to close the stream?

Thanks...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

乖乖 2024-10-18 12:54:41

您应该关闭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 中。使用它意味着您不必处理 close() 可能抛出的可能但很少有用的 IOException

You should close the FileOutputStream, not the ZipOutputStream, because the former is what actually consumes system resources.

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

The IOUtils class is found in Jakarta Commons IO. Using it means that you don't have to deal with the possible-but-rarely-useful IOException that can be thrown by close().

时光磨忆 2024-10-18 12:54:41

您应该跟踪是否向 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 标志。

You should track if you added stuff the zip stream and close it only when things were added:

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

of if you don't need the count just use a boolean flag.

ら栖息 2024-10-18 12:54:41

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

我认为这是 Java 的问题,当没有文件可压缩时,Java 无法处理这种情况。

IE:

int itemsToAdd=0;
//....

if ( itemsToAdd > 0 ) {

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

Instead of closing the stream only when things are added, what I did is a condition check to see if there was anything to zip, before running the zip code. This helped me to simplify the process and I think can be used in general to handle the "ZIP file must have at least one entry" problem. True that closing zos may throw other exceptions, but that is rare.

I think it is problem with Java, that doesn't handle the case when there are no files to zip.

i.e:

int itemsToAdd=0;
//....

if ( itemsToAdd > 0 ) {

    ZipOutputStream zos = new ZipOutputStream(file);
    try {
        //add files to zip
    }
    finally {
        zos.close();
    }
}
§普罗旺斯的薰衣草 2024-10-18 12:54:41

如果您使用 Java 7 或更高版本,可以使用 try-with-resources 以获得更好的可读性

例如:

try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("..."))) {
    // do something with zos
}

If you use Java 7 or above, you can use try-with-resources for better readability

For example:

try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream("..."))) {
    // do something with zos
}
绝對不後悔。 2024-10-18 12:54:41

使用 Java 7 或更高版本,只需 try-with-resource 就足以关闭 ZipOutputStream,无需调用 close() 或 closeEntry() 方法来刷新缓冲区数据并关闭流。

检查了ZipOutputStream::close()的代码,它会调用finish(),并且在finish方法中,有如下检查,这意味着当流关闭时会自动调用closeEntry。

public void finish() throws IOException {
ensureOpen();
if (finished) {
    return;
}
if (current != null) {
    closeEntry();
}
// write central directory
long off = written;
for (XEntry xentry : xentries)
    writeCEN(xentry);
writeEND(off, written - off);
finished = true;

}

Using Java 7 or above, just try-with-resource would be enough to close ZipOutputStream, and there is no need to call close() or closeEntry() methods to flush the buffer data and close the stream.

Checked the code of ZipOutputStream::close(), it would call finish(), and inside the finish method, there is a check as following, which means that the closeEntry would be called automatically when the stream closed.

public void finish() throws IOException {
ensureOpen();
if (finished) {
    return;
}
if (current != null) {
    closeEntry();
}
// write central directory
long off = written;
for (XEntry xentry : xentries)
    writeCEN(xentry);
writeEND(off, written - off);
finished = true;

}

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文