Формат и структура ZIP-архива.
Чтобы перейти к непосредственному кодированию, сначала рассмотрим структуру ZIP-архива, и каким образом информация хранится в нем.
Здесь надо сразу сделать одно замечание. В дданной статье не будет рассмотрена возможность паковки и распаковки контента с его предварительной шифровкой, т.е. мы исходно предполагаем, что файлы архива обычные, не шифрованые, и неупакованы, в так называемые, самораспаковывающиеся файлы, которые зачастую используются в системе Windows, для хранения инфы.
Итак начинаем
Zip-архив состоит из трех крупных частей, каждая из которых выполняют свою роль во всем массиве данных
- Первая часть представляет собой массив спакованых данных . Имено в ней и расположены все части необходимой для нас информации.
- Вторая часть выполняет роль каталога архива, в которой расположены все описания и информация о включнном в архив файла.
- Последняя часть представляет собой заголовок , описывающий непосредственно сам ZIP-архив, а также в ней расположен комментарий к архиву, в котором сохраняется информация об архиве. Комментарий может отсутствовать. Вернее он практически всегда отсутвует, но его наличие вернее его отсутствие с возможным присутствием только осложняет жизнь программисту.
Каждая из частей начинается уникальным идентификатором, который однозначно определяет часть архива. Этот идентификатор расположен всегда в начале любой записи.
Нашу информацию мы начнем со структуры последней часть архива, которая называется глобальный заголовок. Этот заголовок представляет собой 22-байтную запись, расположенную в конце файла архива, сразу перед комметарием.
Вот его расшифровка.
-
4:
06054B50
:
- идентификатор этого заголовка. 2:
disk:
- номер диска2:
disk_start:
- номер диска начального2:
disk_entries:
- число файлов на диске2:
entries:
- число файлов в ахиве4:
size:
- размер в байтах дирректории архива4:
offset:
- смещение до директории архива т начала файла архива2:
comment_size:
- размер следующего за этими двумя байтами комментарием.
Для распаковки всего архива в нашем конкретном случае, этот заголовок вообще не представляет не какой конкретной информации, за исключением лишь случая получения возможной информации, в случае ошщибочной распаковки данных.
Cледующим мы рассмотрим вторую часть ZIP-архива, которая предназначена для сохранении информации о содержимом архива, т.е. просто его дирректория. Этот блог необходим для визуального управления архивом при его модификации, частичной или конкретной распаковки, а также обновлением, пополнением и засены разных частей архива. Вот его сруктура
-
4 : 02014B50 :
- идентификатор этого заголовка. 2 : version :
- версия архива (2.0)2 : version_extracted :
- версия паковки (1.0)2 : flag :
- флаг2 : compression :
- указатель на степень сжатия (0-не сжат)2 : mtime :
- время последнеймодификации объекта2 : mdate :
- дата последней модификации объекта4 : crc :
- циклический контрольный код сrс324 : compressed_size :
- размер объекта в байтах после паковки4 : size :
- размер объекта в байтах исходно2 : filename_len :
- длина имени файла2 : extra_len :
- размер дополнительных данных2 : comment_len :
- размер комментарием.2 : disk :
- номер носителя.2 : internal :
- уровень вложения4 : external :
- внешние данные (10-фолдер)4 : offset :
- смещенние от начала файла до объекта.
За этим заголовком непосредственно располагаются данные , которые определяются этим заголовком, а имено {имя файла в байтах длиной по полю 11}, {байты из поля 12},{коментарий по полю 13}.
Используя этот блок записей мы однозначно строим структуру архика. Число записей этого блока выбирается из поля 5 блока с сигнатурой 0605..
Ну вот наконец мы и подошли к основному блоку данных архива. Опять колличество записей в этом блоке равно числу из поля 5 с сигнатурой 0605..., но его содержание уже другое.
Каждая запись состоит из заголовка и данных. Заголовок состоит из следующих полей
4 : 04034B50 :
- идентификатор этого заголовка.2 : version :
- версия архива (2.0)2 : flag :
- флаг2 : compression :
- указатель на степень сжатия (0-не сжат)2 : mtime :
- время последнеймодификации объекта2 : mdate :
- дата последней модификации объекта4 : crc :
- циклический контрольный код сrс324 : compressed_size :
- размер объекта в байтах после паковки4 : size :
- размер объекта в байтах исходно2 : filename_len :
- длина имени файла2 : extra_len :
- размер дополнительных данных
и Следующих за ним сначала {имя файла в байтах длиной по полю 10}, {байты из поля 11}
и самих данных размером в байтах из поля 8. Наличие паковки определяется либо неравенством полей 8 и 9, но однозначно - не нулевым значением поля 4.
Вот в принципе и все. Здесь уместно сделать несколько замечаний . Как видно из структуры заголовков для данных и дирректории, проглядывается приличное дублирование данных, которое позволяет независимо распаковывать архив, не копаясь в дирректории, а просто сканировать архив с начала файла, поочедно расифровывая сигнатуры данных, считывая как сами данные, так и их заголовки. Такая структура архива позволяет заметно ускорить процес распаковки, применяя меньше затрат для этой, не совсем простой операции.