@StMechanus

Получить список файлов из ZIP

Есть байт-код zip файла. Необходимо получить список файлов в архиве. Смотрел спецификацию — пока очень сумбурно все. Решил глянуть код в хекс редакторе, обратил внимание, что все файлы в архиве описаны в конце архива. Вот выдержка из кода тестового архива:

Код:
04 00 00 80 08 00 00 0C 00 18 00 00 00 00 00 00 00 00 00 B4 81 00 00 00 00 50 65 72 73 6F 6E 2E 63 6C 61 73 73 55 54 05 00 03 8A 44 71 52 75 78 0B 00 01 04 E8 03 00 00 04 E8 03 00 00 50 4B 01 02 1E 03 14 00 00 00 08 00 53 71 61 43 77 E4 43 50 16 7D 0A 00 BC C4 0A 00 08 00 18 00 00 00 00 00 00 00 00 00 B4 81 76 04 00 00 74 65 73 74 2E 67 69 66 55 54 05 00 03 3E 9A 73 52 75 78 0B 00 01 04 E8 03 00 00 04 E8 03 00 00 50 4B 05 06 00 00 00 00 02 00 02 00 A0 00 00 00 CE 81 0A 00 00 00

Текстовое представление:

...................´.....Person.classUT....DqRux....è....è...PK..........SqaCwäCP.}..¼Ä..............´.v...test.gifUT...>.sRux....è....è...PK.......... ...Î…

Подскажите, как обработать архив, чтобы получить список файлов в нем
  • Вопрос задан
  • 6917 просмотров
Решения вопроса 1

Ну и собственно пример выше, разобранный чуть подробнее:


50 4B 03 04 //сигнатура хедера локального файла, читать как 0x04034b50
14 00 // version needed to extract, зависит от фич, использованных при 
      // создании архива, в основном различные алгоритмы сжатия
      // 0x14 соответствует версия 2.0
	
00 00 // general purpose bit flag - свалка различных флагов. Некоторые используются
      // разными алгоритмами, некоторые не используются вообще, некоторые зарезервированы
      
08 00 // метод сжатия, в данном случае Deflate
0D 9D и  5E 43 // DOS-время последней модификации файла, см. структуру FILETIME в WinAPI

33 C3 3A 4D // CRC-32 файла
30 04 00 00 // размер сжатого файла, 1072 байт
80 08 00 00 // размер исходного файла, 2176 байт
0C 00 // совершенно верно, длина имени файла
1C 00 // длина дополнительного поля
50 65 72 73 6F 6E 2E 63 6C 61 73 73 // собственно искомое имя файла. Никакого юникода, старый добрый ASCII

Надеюсь это помогло, если остались вопросы - задавайте, я в своё время немало головной боли помел с зип-файлами.

Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 11
mrstrictly
@mrstrictly
Как-то так:

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

public class LsZip {
    public static void main(String[] args) throws Exception {
        byte[] zipBytes = ...;
        ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zipBytes));
        ZipEntry entry;
        while ((entry = zis.getNextEntry()) != null) {
            // здесь делайте то, что вам требуется с entry.getName()
        }
    }
}
Ответ написан
Комментировать
LuckyStarr
@LuckyStarr
Использовать класс ZipFile. Тут пример.
Ответ написан
Комментировать
@betal
рекомендую hex editor neo
там есть шаблоны популярных форматов, можно понять какой бит за что отвечает.
А так ничего не остается как читать подробную документацию.
По зипу (хотя может с rar путаю) если мне память не изменяет, вначале краткое описание файлов, в конце их содержимое. (где название упоминается не помню, может и в конце)
Причем можно удалить в начале краткое описание конкретного файла (поправив кучу crc), а в конце оставить, получится таким образом скрытый файл.
Готовые библиотеки почему не используете?
Ответ написан
Комментировать
@StMechanus Автор вопроса
Уточню, ребят. Я хочу работать с байт кодом напрямую. Очень интересно написать свое решение — так званный тренинг для себя. Просто не получается разобраться в спецификации
Ответ написан
@StMechanus Автор вопроса
Интересный момент, согласно спецификации header для файла в цетральной дериктории должен соответствовать 0x02014b50, пытался найти такую последовательность байт в нескольких архивах — и соответствий не нашел. Однако, я обратил внимание на последовательность 0х504B0102. Таких последовательностей в архиве ровно столько же сколько и файлов (проверял на нескольких архивах). С чем это может быть связано. Знающие люди, помогите понять
Ответ написан
@StMechanus Автор вопроса
Тоже самое и для local header, должно быть 0х0x04034b50, на деле же имеем 0х504b0304. Опять же количество таких последовательностей равно количеству файлов
Ответ написан
Комментировать
@StMechanus Автор вопроса
Продолжение наблюдения: после такой сигнатуры «local header'a» собственно его структура сохраняет свою истенность. Приведу пример.

50 4B 03 04 14 00 00 00 08 00 0D 9D 5E 43 33 C3 3A 4D 30 04 00 00 80 08 00 00 0C 00 1C 00 50 65 72 73 6F 6E 2E 63 6C 61 73 73

Что соответствует такому отображению в хекс редакторе

PK..........^C3Ã:M0...........Person.class

Так вот исходя из формата local header'a, перед именем файла следует 2 байта указывающие длину дополнительного поля, а перед ними 2 байта, указывающее длину имени файла.
Собственно значение 0С (12) соответствует длине имени Person.class

Жду рассуждений на эту тему
Ответ написан
Комментировать

Судя по комментариям выше, вы уже во всём разобрались (кроме порядка байтов). В целом всё верно, нужно пройтись по всем local file header и достать из них имя. В качестве примера посоветовал бы почитать исодники minizip, входящей в состав zlib.

В частности https://github.com/madler/zlib/blob/master/contrib/minizip/miniunz.c#L234 и подробней о парсинге хедера в https://github.com/madler/zlib/blob/master/contrib/minizip/unzip.c#L1136

Это не Java а C, но, учитывая что вещи довольно низкоуровневые, понять можно.

Ответ написан
Комментировать
Если говорить о разборе метаинфы из джавы, я бы в первую очередь посмотрел на исходник готового решения -- метод создает энтри с основной информацией
Ответ написан
Комментировать
@aryank4564
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы