太长不看?直接用 zip-saver
一、zip 文件格式简介
zip 文件大致可以分成三个个部分:
- 文件部分
- 文件部分包含了所有的文件内容,每个文件都有一个文件头,文件头包含了文件的元信息,比如文件名、文件大小、文件的压缩方式等等。
- 中央目录部分
- 中央目录部分包含了所有文件的元信息,比如文件名、文件大小、文件的压缩方式等等。
- 目录结束标识 - 目录结束标识标识了中央目录部分的结束。包含了中央目录的开始位置、中央目录的大小等信息。 图片来自:en.wikipedia.org/wiki/ZIP_(f…
对于每一个文件,他在 zip 中包含三部分
- 本地文件头( Local File Header)-- 图片来自:goodapple.top/archives/70…
- 文件内容
- 数据描述符( Data descriptor)-- 图片来自:goodapple.top/archives/70…
数据描述符是可选的,当本地文件头中没有指明 CRC-32 校验码和压缩前后的长度时,才需要数据描述符
中央目录区的数据构成是这样的 -- 图片来自:goodapple.top/archives/70…
目录结束标识的数据构成是这样的 -- 图片来自:goodapple.top/archives/70…
二、代码实现
有了上面的信息之后,不难想到生成一个 zip 文件的步骤:
- 生成文件部分
- 构造固定的文件信息头
- 追加文件内容
- 计算文件的 CRC32 校验码
- 生成数据描述符
- 生成中央目录部分
- 构造固定的中央文件信息头
- 计算文件的偏移量
- 生成目录结束标识
- 构造固定的目录结束标识
- 计算中央目录的大小和偏移
1. 生成本地文件头(local file header)
根据的结构,我们很容易得知:一个 的大小是 个字节
其中是文件名的长度,是扩展字段的长度,在这里我们不考虑扩展字段,那么最终大小就是
在中我可以直接用来存储一个字节,又因为 zip 是采用小端序,为了方便操作, 那么变量就可以这样定义:
js
代码解读
复制代码
定义完 local file header 变量后我们就可以往里面塞一些东西了
js
代码解读
复制代码
到此,一个就生成好了
2. 文件内容追加
文件内容追加这一步很简单,这里我们不考虑压缩文件,直接将文件转为 并计算文件的 CRC32 校验码,然后追加到后面即可
js
代码解读
复制代码
3. 数据描述符(Data descriptor)生成
数据描述符用来表示文件压缩与的结束,根据他的编码格式,他包含的信息只有四个:固定的标识符、CRC-32校验码,压缩前的大小,压缩后的大小,这里我们暂且不考虑数据的压缩, 要生成他也很简单:
js
代码解读
复制代码
至此,一个文件在zip中所有的信息就已经都可以生成了,接下来就需要生成中央目录信息了
4. 中央目录区生成
根据上面的图,我们知道, 中央目录区也是由一个一个的文件头组成,每一个文件头对对应着一个真实文件的信息,每个文件信息大小是46 + n + m + k,其中n是文件名称的大小,m是扩展字段的大小,k是文件注释的大小。 在这里,我们可以暂时不必管扩展字段,先计算一下中央目录区的总大小:
js
代码解读
复制代码
然后,创建一个变量存储中央目录区的数据
js
代码解读
复制代码
接下来就可以通过循环,将所有文件的信息都写入中央目录区
js
代码解读
复制代码
最后,再生成 目录结束标识
js
代码解读
复制代码
5. 拼接完整数据
完成了上面所有的步骤之后,我们只需要把数据都拼接起来就可以了
js
代码解读
复制代码
ok,搞定!
6. 完整的实现
github.com/EatherToo/z…
三、总结
经过上面的步骤,我们就可以生成一个zip文件了,当然,这里只是一个简单的实现,zip文件格式还有很多细节,比如压缩算法、加密压缩等等,这里都没有涉及到,后面有时间再来完善吧。
参考资料:
- goodapple.top/archives/70…
- en.wikipedia.org/wiki/ZIP_(f…
- github.com/jimmywartin…
版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/rfx/57358.html