ZIP файл состоит из трех областей:
- сжатые/несжатые данные, (последовательность структур типа
LocalFileHeader
, сами данные и необязательныхDataDescriptor
) - центральный каталог (последовательность структур
CentralDirectoryFileHeader
) - описание центрального каталога (
End of central directory record (EOCD)
)
С начала файла идет набор из LocalFileHeader
, непосредственно данные и (необязательно) структура Data descriptor
. Затем структуры типа CentralDirectoryFileHeader
для каждого файла и папки в ZIP архиве и завершает все это структура End of central directory record
.
Local File Header
Используется для описания метаданных файла (имя файла, контрольная сумма, время и дата модификации, сжатый/несжатый размер). Как правило сразу после этой структуры следует содержимое файла.
struct LocalFileHeader { // Обязательная сигнатура, равна 0x04034b50 uint32_t signature; // Минимальная версия для распаковки uint16_t versionToExtract; // Битовый флаг uint16_t generalPurposeBitFlag; // Метод сжатия (0 - без сжатия, 8 - deflate) uint16_t compressionMethod; // Время модификации файла uint16_t modificationTime; // Дата модификации файла uint16_t modificationDate; // Контрольная сумма uint32_t crc32; // Сжатый размер uint32_t compressedSize; // Несжатый размер uint32_t uncompressedSize; // Длина название файла uint16_t filenameLength; // Длина поля с дополнительными данными uint16_t extraFieldLength; // Название файла (размером filenameLength) uint8_t *filename; // Дополнительные данные (размером extraFieldLength) uint8_t *extraField; }; |
compressedSize
при использовании сжатия или размером uncompressedSize
в противном случае.
Иногда бывает невозможно вычислить данные на момент записи LocalFileHeader
, тогда в crc32
, compressedSize
и uncompressedSize
записываются нули, третий бит в generalPurposeBitFlag
ставится в единицу, а после LocalFileHeader
добавляется структура типа DataDescriptor
.
Data descriptor
Если по какой-то причине содержимое файла невозможно создать одновременно с заголовком типа LocalFileHeader
, то сразу после него следует структура DataDescriptor
, где идет находится дополнение метаданных для LocalFileHeader
(контрольная сумма, сжатый/несжатый размер).
Откровенно говоря, мне такие файлы не попадались, поэтому больше того, чем написано в википедии сказать не могу.
struct DataDescriptor { // Необязательная сигнатура, равна 0x08074b50 uint32_t signature; // Контрольная сумма uint32_t crc32; // Сжатый размер uint32_t compressedSize; // Несжатый размер uint32_t uncompressedSize; }; |
Central directory file header
Расширенное описание метаданных файла. Содержит дополненную версию LocalFileHeader
(добавляются поля номер диска, файловые атрибуты, смещение до LocalFileHeader
от начала ZIP файла).
struct CentralDirectoryFileHeader { // Обязательная сигнатура, равна 0x02014b50 uint32_t signature; // Версия для создания uint16_t versionMadeBy; // Минимальная версия для распаковки uint16_t versionToExtract; // Битовый флаг uint16_t generalPurposeBitFlag; // Метод сжатия (0 - без сжатия, 8 - deflate) uint16_t compressionMethod; // Время модификации файла uint16_t modificationTime; // Дата модификации файла uint16_t modificationDate; // Контрольная сумма uint32_t crc32; // Сжатый размер uint32_t compressedSize; // Несжатый размер uint32_t uncompressedSize; // Длина название файла uint16_t filenameLength; // Длина поля с дополнительными данными uint16_t extraFieldLength; // Длина комментариев к файлу uint16_t fileCommentLength; // Номер диска uint16_t diskNumber; // Внутренние аттрибуты файла uint16_t internalFileAttributes; // Внешние аттрибуты файла uint32_t externalFileAttributes; // Смещение до структуры LocalFileHeader uint32_t localFileHeaderOffset; // Имя файла (длиной filenameLength) uint8_t *filename; // Дополнительные данные (длиной extraFieldLength) uint8_t *extraField; // Комментарий к файла (длиной fileCommentLength) uint8_t *fileComment; }; |
End of central directory record (EOCD)
Эта структура записывается в конце файла. Содержит следующие поля: номер текущего диска, количество записей CentralDirectoryFileHeader
в текущем диске, общее количество записей CentralDirectoryFileHeader
.
struct EOCD { // Обязательная сигнатура, равна 0x06054b50 uint32_t signature; // Номер диска uint16_t diskNumber; // Номер диска, где находится начало Central Directory uint16_t startDiskNumber; // Количество записей в Central Directory в текущем диске uint16_t numberCentralDirectoryRecord; // Всего записей в Central Directory uint16_t totalCentralDirectoryRecord; // Размер Central Directory uint32_t sizeOfCentralDirectory; // Смещение Central Directory uint32_t centralDirectoryOffset; // Длина комментария uint16_t commentLength; // Комментарий (длиной commentLength) uint8_t *comment; }; |
Папки в ZIP файле представлены двумя структурами LocalFileHeader
и CentralDirectoryFileHeader
с нулевым размером и контрольной суммой. Название папки заканчивается слешем «/».