zip

zip格式调研

调研下zip文件结构

Posted by BaiYe on March 17, 2020

zip格式调研

背景

想用下zip的无压缩打包,故调研下下zip格式协议。

调研结论

  1. go、php、c、c++、lua均有开源库可已处理zip包,使用方式很简单。
  2. 不压缩只打包zip可以支持range获取数据,但是需要三次位移才能完成。先读取尾部22个字节,获取到目录结束标记。再通过目录结束标记中的偏移量等信息下载中心目录信息,从中心目录信息中获取到每个文件的偏移量信息和文件名信息。再通过对应文件的偏移量信息读取该文件的数据段,再通过数据段的local file header定位获取到该文件的数据。
  3. zip结构主要由 文件数据段 + 中心目录段 + 结尾目录段 这三部分构成,除了结尾目录端是固定22字节(无注释情况下)外,其他两个段都是变长的,影响中心目录段长度的是文件数和各文件的文件名长度。
  4. zip结尾目录段的注释部分可以自定义(ZIP file comment length + ZIP file comment),通过zip -z ./test.zip 就可以给zip文件添加注释。

zip打包格式说明

[local file header + file data + data descriptor]{1,n} + [central directory] + [end of central directory record] [文件头+文件数据+数据描述符]{可重复n次}+核心目录信息+目录结束标识

主要就是[local file header + file data]。

记录了压缩文件的目录信息,在这个数据区中每一条纪录对应在压缩源文件数据区中的一条数据。

每一条纪录对应信息。

range获取数据方式:

核心目录结尾段:

先读取结尾22个字节获取到zip文件的End of central directory record,从End of central directory record获取到核心目录的偏移量、核心目录结构总数、核心目录大小。

核心目录段:

再读取完整核心目录,根据核心目录结构总数遍历每个结构,根据文件名后缀取图片或者视频的偏移量(relative offset of local header)、数据长度(compressed size)、文件名长度(file name length)、扩展预长度(extra field length)。

数据段:

然后根据偏移量+30+文件名长度+扩展预长度为偏移量,数据长度为长度获取数据。

也就是一个文件需要读取三次获取到所需要的数据。这种方式需要打包zip版本固定,否则可能改变导致不兼容。

各语言支持

  • php: http://php.net/manual/zh/ref.zip.php
  • c/c++: https://libzip.org/documentation/
  • lua: http://luazip.luaforge.net/manual.html#introduction
  • golang: import “archive/zip”

参考资料

  • https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.2.0.txt
  • http://blog.csdn.net/a_flying_bird/article/details/46625873
  • http://blog.csdn.net/a200710716/article/details/51644421
  • http://blog.csdn.net/delphiwcdj/article/details/39717617