Apache Commons: UnsupportedZipFeatureException (LZMA)

795 views Asked by At

I want to unzip .zip files (with .jpg files inside) that were created using Windows 10's zipping feature.

First I tested it with Java 8's native util.zip.ZipEntry but kept getting an invalid CEN header (bad compression method) error, which seems to be caused by an incompatibility with Win10's compression.

Because of that I switched to Apache Common's Compress library (version 1.2). The first two images in the archive unzip fine but the third always throws an exception:

org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException: Unsupported compression method 14 (LZMA) used in entry image3.jpg

How do I fully unzip this archive with the Compress library? Is that even possible?

My code:

ZipFile z = new ZipFile(zippath);
Enumeration<ZipArchiveEntry> entries = z.getEntries();

while(entries.hasMoreElements()) {
    ZipArchiveEntry entry = entries.nextElement();
    System.out.println("Entry: "+entry.getName());
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipfolder+"\\"+entry.getName()));
    BufferedInputStream bis = new BufferedInputStream(z.getInputStream(entry));
    byte[] buffer=new byte[1000000];
    int len=0;

    while((len=bis.read(buffer,0,1000000))>0) {
        bos.write(buffer, 0, len)  ;
    }
    bis.close();
    bos.close();
}
1

There are 1 answers

0
Neph On BEST ANSWER

I also tested it with the "LZMA" code provided on the examples site (which also includes adding the "xz" library) and even a CompressorInputStream but no matter what I did, I kept getting some type of exception, e.g.:

org.tukaani.xz.UnsupportedOptionsException: Uncompressed size is too big

Fortunately there's an inofficial fix for that, posted as an answer for this question. The explanation:

The reason your code isn't working, is that Zip LZMA compressed data segments have a different header compared to normal compressed LZMA files.

Using getInputstreamForEntry (which was posted in the answer), my code is now able to deal with both LZMA and non-LZMA files in a zip archive:

ZipFile z = new ZipFile(zipfile);
Enumeration<ZipArchiveEntry> entries = z.getEntries();

while(entries.hasMoreElements()) {
    ZipArchiveEntry entry = entries.nextElement();
    System.out.println("Entry: "+entry.getName());
    BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(unzipfolder+"\\"+entry.getName()));
    BufferedInputStream bis = null;

    try {
        bis  = new BufferedInputStream(z.getInputStream(entry));
    } catch(UnsupportedZipFeatureException e) {
        bis  = new BufferedInputStream(getInputstreamForEntry(z, entry));
    }

    byte[] buffer=new byte[1000000];
    int len=0;
                        
    while((len=bis.read(buffer,0,1000000))>0) {
        bos.write(buffer, 0, len)  ;
    }
    bis.close();
    bos.close();
}