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
}
精彩评论