ZipException: error in opening zip file

I'm working on a method which will take a zipped file, unzip it, and return a new file/directory containing all the unzipped files. The goal is to then take that directory and extract an excel document from it and then convert it into a Workbook class I built (which is fully unit tested and works fine). The problem is that I'm getting the following exception:

java.util.zip.ZipException: error in opening zip file
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:215)
at java.util.zip.ZipFile.<init>(ZipFile.java:145)
at java.util.zip.ZipFile.<init>(ZipFile.java:159)
at com.atd.core.datamigrator.BulkImageUpload.createWorkbook(BulkImageUpload.java:54)
at com.atd.core.datamigrator.BulkImageUpload.importImages(BulkImageUpload.java:38)
at com.atd.core.datamigrator.BulkImageUpload.main(BulkImageUpload.java:236) 

Here is my code

private Workbook createWorkbook(File file) {
    File unZipedFile = unZip(file);
    File[] files = unZipedFile.listFiles();
    Workbook wBook = null;

    for (int i = 0; i < files.length; i++) {
        if (files[i].getName().contains(".xls")) {
            try {
                File f = files[i];
                ZipFile zip = new ZipFile(f);
                wBook = new Workbook(zip);
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        }
    }
    return wBook;
}

private File unZip(File input) {
    File output = new File("unzippedFile");
    OutputStream out = null;
    try {
        ZipFile zipFile = new ZipFile(input);
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) {
            ZipEntry entry = entries.nextElement();
            File entryDestination = new File(output, entry.getName());
            entryDestination.getParentFile().mkdirs();
            InputStream in = zipFile.getInputStream(entry);
            ZipInputStream zis = new ZipInputStream(in);
            out = new FileOutputStream(entryDestination);
            out.write(zis.read());
            out.flush();
            out.close();
        }
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return output;
}

I know this is a problem with the unzip method because when I use File f = new File("some path") instead of using the unzipped file, it works fine.

Also, File I/O was never my strong point, so be nice :)

Jon Skeet
people
quotationmark

Okay, I now believe that this is the problem:

ZipInputStream zis = new ZipInputStream(in);
out = new FileOutputStream(entryDestination);
out.write(zis.read());
out.flush();
out.close();

You're creating a new file, and writing a single byte to it. That's not going to be a valid Excel file of any description. You're also failing to close streams using finally blocks, but that's a different matter. To copy the contents of one stream to another, you want something like:

byte[] buffer = new byte[8192];
int bytes;
while ((bytes = input.read(buffer)) > 0) {
    output.write(buffer, 0, bytes);
}

That said, you'd be better off using a 3rd party library to hide all of this detail - look at Guava and its ByteStreams and Files classes for example.

It's worth taking a step back and working out why you didn't spot this problem for yourself, by the way. For example, the first thing I'd have done would be to look at the directory where the files were unzipped, and try to open those files. Just seeing a bunch of 1-byte files would be a bit of a giveaway. When trying to diagnose an issue, it's vital that you can split a big problem into small ones, and work out which small one is at fault.

people

See more on this question at Stackoverflow