ZipInputStream.getNextEntry returns null on some zip files

spring_dev101 picture spring_dev101 · Mar 20, 2013 · Viewed 14.7k times · Source

I have a simple code to extract zip files, it was working just fine as expected but during my test I tried my code with some zip files (fonts, icons and templates I downloaded from internet) just to make sure it should extract any zip files provided, but its not working with some zip files, here is the minimized code to regenerate this issue:

package com.test.mytest;

import java.io.FileInputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;

public class ZipExtractTest {

    public static final String ZIP_FILE = "/Users/XXXXX/Downloads/janne.zip";

    public static void main(String[]args) {
        unzipFile(ZIP_FILE);
        unzipStream(ZIP_FILE);
    }

    public static void unzipFile(String zipName) {
        try {

            ZipFile zf = new ZipFile(zipName);

            Enumeration ent = zf.entries();

            while(ent.hasMoreElements()) {
                System.out.println(ent.nextElement());
            }

        } catch(Exception e) {
            System.out.println(e);
        }
    }

    public static void unzipStream(String zipName) {
        try {
            ZipInputStream zis = new ZipInputStream(new FileInputStream(zipName));
            ZipEntry ze = zis.getNextEntry();

            if(ze == null) {
                System.out.println("unable to get first entry from zip file");
                zis.close();
                return;
            }

            while(ze != null) {
                System.out.println("Entry Found: " + ze);
                ze = zis.getNextEntry();
            }

            zis.closeEntry();
            zis.close();

        } catch(Exception e) {
            System.out.println(e);
        }
    }
}

actually In my real application i have to extract zip files through inputstreams. In the code above I am trying to extract "janne.zip" I downloaded this file from http://www.iconian.com/fonts/janne.zip I am able to extract it using any zip-tool and surprisingly through "unzipFile(String zipName)" method as well, but with unzipStream(String zipName) method

ZipEntry ze = zis.getNextEntry();

returns null

any help would be appreciated

Answer

Ian Roberts picture Ian Roberts · Mar 20, 2013

Not an answer as to why this particular file doesn't work with java.util.zip, but if you have the option to replace your use of java.util.zip.ZipInputStream with the Apache commons-compress org.apache.commons.compress.archivers.zip.ZipArchiveInputStream (which should be API-compatible) then I've just tested that on your example file and it seems to work successfully.

Generally I find commons-compress to be much more reliable than java.util.zip at unpacking files created by tools other than the java.util.zip classes themselves.

Edit: I've done a bit of debugging in Eclipse and it looks like this particular zip file has a single segment spanning marker of 0x30304b50 before the LOC signature (0x04034b50) of the first entry's local header. This is something that commons-compress knows how to handle but java.util.zip doesn't - if j.u.z.ZipInputStream sees anything other than a LOC signature then getNextEntry() will return null.