大黑 2019-07-01
最近闲着没事,出于探索(折腾)精神,就想搞个大新闻。想来想去,就拿 7-Zip 下手吧。正好我手头有一个自定义格式的文件包操作库,但一直懒得写一个图形管理工具,能直接让 7z 支持这个格式岂不美哉?
本文不会深入介绍 7z 的运行流程,毕竟我也是很有针对性的阅读代码,仅仅阅读了与存档包格式处理相关的代码,更深入的我也没读下去,以后再说吧。另外我也不想写太多,这个系列就写到能够读取存档包(只读)为止,写入和修改部分欢迎大家自己研究。
先给想要阅读 7z 代码的朋友提个醒,7z 这个代码。。对外接口部分的文档确实是比较充分了,但是如果想添加新的格式,或者添加新的压缩算法,这部分代码注释很少,你必须自己完整阅读前后文代码,自己分析运行流程,然后祈祷自己分析的没有偏差。
7-Zip 官网:https://7-zip.org/
7z 没有官方 git 仓库,虽然是开源的,但源码是以 7z 压缩包的形式提供的,看不到修改提交记录就很难受。源码是以 LGPL 协议开源的,想要改完代码闭源发布的请小心了。
7z 的功能其实分为 3 个部分:Format、Codec、Hasher,顾名思义,就是文件格式、压缩算法、哈希(校验)算法。完整的功能列表可以执行 7z i
命令,看到长长的格式列表了么,官方说支持 30 多种格式的解压。
对于之前没有深入使用过压缩文件处理工具的读者,这里顺便科普一下。我们说的压缩文件,其实分为两部分:压缩算法(Compress)和存档包格式(Archive)。
压缩算法是输入一段数据,输出压缩后的数据,注意这里没有文件和文件夹的概念,仅仅是处理一段数据。我们常见的压缩算法如 deflate、lzma。网页开发的同学应该都知道 deflate(gzip),web 服务器必开的一个选项了吧,网页数据传输不牵扯任何文件格式,仅仅是把数据流压缩发送出去。
存档包定义了文件和文件夹的存储方式,它是一种打包格式,打包的可以是一个文件,也可以是多个文件,其中还会包含其他信息,如哈希值、时间戳、文件权限、注释等。gzip 工具就是对 deflate 压缩算法的简单封装,只支持单个文件压缩解压。tar 存档包格式就是一种纯打包的格式,把多个文件或文件夹打包成一个单独的文件,它本身不具备任何压缩功能。我们常见的 .tar.gz 格式就是先打包成 tar,再用 gzip 进行压缩。
解压 7z 源码后,可以看到这 4 个文件夹。
7z 的大部分代码都是 C++ 写的,少部分需要高性能的代码是 C 写的,最最核心的几个压缩算法函数,是汇编写的。DOC 目录中有 7z 格式的介绍,和源码各个目录的简介,看看就好。
从源码中大量的 .mak 文件就可以看出,官方应该是直接通过 nmake 工具在命令行中编译的。但也提供了 VS 项目文件,在 CPP/7zip/Bundles
和 CPP/7zip/UI
目录下。
我们重点关注 Bundles 目录下的这 2 个项目:
7za.exe
,仅支持 7z 等少数几种常见格式的命令行工具7z.dll
,这才是 7z 的核心,里面包含所有支持的格式按照惯例,都是先把 Alone 项目编译一遍,但需要注意,项目默认输出目标是 C:\UTIL\7za.exe
,是写死的路径,最好自己到 项目属性->链接器->输出文件
中改改。如果编译出现资源重复错误,把 Spec/resource.rc
文件从项目中移除即可。
源码的核心都在 CPP\7zip
目录下:
既然我们的目标是让 7z 支持更多的存档包格式,那么就只关注 Archive 目录,照葫芦画瓢搞出其他格式不就行了。
哈哈,当然没这么简单的,下一篇文接着讲遍布源码各处的重要接口。