zip文件格式

来源:互联网 发布:马努吉诺比利数据 编辑:程序博客网 时间:2024/04/29 01:58

zip文件格式

说明

本人根据自己的学习过程,适当理解,并作下笔记,以便查阅。这里暂不包含zip64部分。

整体结构

简单归纳总结下,zip文件格式由文件数据区、中央目录结构,中央目录结束标志组成。其中中央目录结束节又有一个字段保存了中央目录结构的偏移。整体结构如下图

zip文件结构

分区描述

中央目录结束标志

中央目录结束标志一般位于文件的末尾。由于它也有字段指向了中央目录开始处的偏移, 所以把它放在最前面描述。它被用来标识中央目录结束。可以通过读取它来找到中央目录并解析整个文件结构。该结构具体如下:

struct EndLocator{    ui32 signature;   //目录结束标记,(固定值0x06054b50)    ui16 elDiskNumber;  //当前磁盘编号    ui16 elStartDiskNumber;  //中央目录开始位置的磁盘编号    ui16 elEntriesOnDisk;  //该磁盘上所记录的核心目录数量    ui16 elEntriesInDirectory;  //中央目录结构总数    ui32 elDirectorySize;  //中央目录的大小    ui32 elDirectoryOffset;  //中央目录开始位置相对于文件头的偏移    ui16 elCommentLen;  // 注释长度    char *elComment;  // 注释内容};

中央目录结构

中央目录结构位于文件数据区后,它用来保存所有文件的路径信息,和对应文件数据结构区在文件中的偏移。该结构具体如下:

struct DirEntry{    ui32 signature;  // 中央目录文件header标识(0x02014b50)    ui16 deVersionMadeBy;  // 压缩所用的pkware版本    ui16 deVersionToExtract;  // 解压所需pkware的最低版本    ui16 deFlags;  // 通用位标记    ui16 deCompression;  // 压缩方法    ui16 deFileTime;  // 文件最后修改时间    ui16 deFileDate;  // 文件最后修改日期    ui32 deCrc;  // CRC-32校验码    ui32 deCompressedSize;  // 压缩后的大小    ui32 deUncompressedSize;  // 未压缩的大小    ui16 deFileNameLength;  // 文件名长度    ui16 deExtraFieldLength;  // 扩展域长度    ui16 deFileCommentLength; // 文件注释长度    ui16 deDiskNumberStart;  // 文件开始位置的磁盘编号    ui16 deInternalAttributes;  // 内部文件属性    ui32 deExternalAttributes;  // 外部文件属性    ui32 deHeaderOffset;  // 本地文件头的相对位移    char *deFileName;  // 目录文件名    char *deExtraField;  // 扩展域    char *deFileComment; // 文件注释内容};

中央目录结构区是由中央目录结构的数组组成,这个结构只有目录文件名,扩展域,文件注释内容长度是不定的,并且可以在这个结构中获取它的长度,那么通过此就可以遍历出所有的文件。设当前中央目录结构偏移为current_offset,下个中央目录结构偏移为next_offset,则计算公式为:

next_offset = current_offset + sizeof(DirEntry) - 3*sizeof(char*) + deFileNameLength + deExtraFieldLength + deFileCommentLength;

其中CRC32校验码为对应的文件压缩数据的CRC32的校验码,如对应文件的数据压缩数据的CRC32与这里的值不同,则数据损坏。
通过中央目录结构的deHeaderOffset字段可以直接获取到对应文件的文件数据区结构的文件偏移,就可以直接获取到对应文件的压缩数据了。

文件数据区

文件数据区是保存所有压缩文件数据的区,它位于文件头,并由压缩数据结构的数组组成。其结构如下:

struct Record{    ui32 signature;  // 文件头标识,值固定(0x04034b50)    ui16 frVersion;  // 解压文件所需 pkware最低版本    ui16 frFlags;  // 通用比特标志位(置比特0位=加密)    ui16 frCompression;  // 压缩方式    ui16 frFileTime;  // 文件最后修改时间    ui16 frFileDate;  //文件最后修改日期    ui32 frCrc;  // CRC-32校验码    ui32 frCompressedSize;  //  压缩后的大小    ui32 frUncompressedSize;  // 未压缩的大小    ui16 frFileNameLength;  //  文件名长度    ui16 frExtraFieldLength;  // 扩展区长度    char* frFileName;  // 文件名    char* frExtraField;  // 扩展区    char* frData; // 压缩数据};

这里的压缩方式frCompression有如下取值:

          0 - The file is stored (no compression)          1 - The file is Shrunk          2 - The file is Reduced with compression factor 1          3 - The file is Reduced with compression factor 2          4 - The file is Reduced with compression factor 3          5 - The file is Reduced with compression factor 4          6 - The file is Imploded          7 - Reserved for Tokenizing compression algorithm          8 - The file is Deflated          9 - Enhanced Deflating using Deflate64(tm)         10 - PKWARE Data Compression Library Imploding         11 - Reserved by PKWARE         12 - File is compressed using BZIP2 algorithm

通过中央目录结构就可以找到文件数据结构,通过文件数据结构获取到压缩数据结构,并通过此结构可以获取到压缩的数据和使用的算法,并可以根据此解压出对应的数据。

crc32

crc32即循环冗余校验,一般用于校验数据是否正确。其实现方式参考http://blog.csdn.net/lickylin/article/details/7857586

总结

zip文件结构比较清晰,可以从位于文件尾的中央文件目录结束区入手,获取到中央目录结构的偏移地址,再遍历中央目录获取到所有的文件,并通过文件数据结构获取到文件数据,数据是否损坏可通过crc32进行校验。

原创粉丝点击