tags:

views:

687

answers:

5

Hi,

we have a piece of code which generates a zip file on our system. Everything is ok, but sometimes this zip file while opened by FilZip or WinZip is considered to be corrupted.

So here is my question: how can we check programmatically if a generated zip file is corrupted?

Here is the code we are using to generate our zip files:

try {
                ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(tmpFile));
                byte[] buffer = new byte[16384];
                int contador = -1;
                for (DigitalFile digitalFile : document.getDigitalFiles().getContent()) {
                    ZipEntry entry = new ZipEntry(digitalFile.getName());
                    FileInputStream fis = new FileInputStream(digitalFile.getFile());
                    try {
                        zos.putNextEntry(entry);
                        while ((counter = fis.read(buffer)) != -1) {
                            zos.write(buffer, 0, counter);
                        }
                        fis.close();
                        zos.closeEntry();
                    } catch (IOException ex) {
                        throw new OurException("It was not possible to read this file " + arquivo.getId());
                    }
                }
                try {
                    zos.close();
                } catch (IOException ex) {
                    throw new OurException("We couldn't close this stream", ex);
                }

Is there anything we are doing wrong here?

EDIT: Actually, the code above is absolutely ok. My problem was that I was redirecting the WRONG stream for my users. So, instead of opening a zip file they where opening something completely different. Mea culpa :(

BUT the main question remains: how programatically I can verify if a given zip file is not corrupted?

+2  A: 

I think you'll see correspondent exception stack trace during zip-file generation. So, you probably wan't to enhance your exception handling.

John Doe
Actually no exception is thrown in the process. The zip file is fully generated, but we can't open it with Filzip, Winzip or any other zip extraction application. :/
Kico Lobo
+1  A: 

ZipOutputStream does not close the underlying stream.

What you need to do is:

FileOutputStream fos = new FileOutputStream(...);
ZipOutputStream zos = new ZipOutputStream(fos);

Then in your closing block:

zos.close();
fos.flush(); // Can't remember whether this is necessary off the top of my head!
fos.close();
Phill Sacre
Well: I tried, but the problem persists.Actually, our problem is happening in a single case only. :/
Kico Lobo
+1  A: 

Perhaps swap the following two lines?;

fis.close();
zos.closeEntry();

I can imagine that the closeEntry() will still read some data from the stream.

Waverick
The problem remains. :/
Kico Lobo
+1  A: 

Your code is basically OK, try to find out which file is responsible for the corrupted zip file. Check whether digitalFile.getFile() always returns a valid and accessible argument to FileInputStream. Just add a bit logging to your code and you will find out what's wrong.

stacker
+1  A: 

You can use the ZipFile class to check your file :

 static boolean isValid(final File file) {
    ZipFile zipfile = null;
    try {
        zipfile = new ZipFile(file);
        return true;
    } catch (ZipException e) {
        return false;
    } catch (IOException e) {
        return false;
    } finally {
        try {
            if (zipfile != null) {
                zipfile.close();
                zipfile = null;
            }
        } catch (IOException e) {
        }
    }
}
Arnaud
Perfect! Didn't know this class. Thank's a lot!
Kico Lobo
If you want to test all the zip file (not only check if it has zip heads) then do a complete read of it using zip file (iterate over its entries and for each one ask for the stream and read it until it ends).
helios
The zip file format is redundant, so you can't for certain make sure that it is not corrupt. Best you can do without having your own implementation is read all the data through `ZipFile` and through `ZipInputStream` and compare secure hashes.
Tom Hawtin - tackline