开发者

Closing ZipOutputStream

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(DeflaterOutputStre开发者_Python百科am.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...


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().


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.


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


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
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜