Apache Commons: UnsupportedZipFeatureException (LZMA)

Я хочу разархивировать файлы .zip (с файлами .jpg внутри), которые были созданы с помощью функции архивирования Windows 10.

Сначала я протестировал его с собственным util.zip.ZipEntry Java 8, но продолжал получать ошибку invalid CEN header (bad compression method), которая, по-видимому, вызвана несовместимостью со сжатием Win10.

Из-за этого я переключился на библиотеку Compress Apache Common (версия 1.2). Первые два изображения в архиве распаковываются нормально, но третье всегда выдает исключение:

org.apache.commons.compress.archivers.zip.UnsupportedZipFeatureException: В записи image3.jpg используется неподдерживаемый метод сжатия 14 (LZMA).

Как полностью разархивировать этот архив с библиотекой Compress? Это вообще возможно?

Мой код:

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();
}
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
0
574
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я также протестировал его с кодом «LZMA», представленным на сайте примеров (который также включает добавление библиотеки «xz») и даже CompressorInputStream, но независимо от того, что я делал, я продолжал получать какие-то исключения. , например:

org.tukaani.xz.UnsupportedOptionsException: Размер несжатого файла слишком велик. большой

К счастью, для этого есть неофициальное исправление, опубликованное как ответ на этот вопрос. Объяснение:

Причина, по которой ваш код не работает, заключается в том, что Zip LZMA сжимает данные сегменты имеют другой заголовок по сравнению с обычным сжатым LZMA файлы.

Используя getInputstreamForEntry (который был опубликован в ответе), мой код теперь может работать как с файлами LZMA, так и с файлами, отличными от LZMA, в zip-архиве:

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();
}

Другие вопросы по теме