今天由于工作需要,需要挑选一个能够进行线程安全的压缩库.
1. 能够机型基本的buffer压缩.
2. 能够进行递归方式的目录结构压缩.
经过挑选发现
1. zlib 是能够多线程安全的,但是它不能够进行目录结构压缩.
2. minizip / miniuzip 是线程安全的,但是它在压缩的时候不能够进行目录压缩,解压缩倒是可以的.
3. zip/unzip 是全能的,但是网站明确表示这个库不能够多线程使用.
下面是我的探索:
Q: zip为什么不支持多线程使用
A: zip的source code中大量使用了全局变量,作为函数间共享的方式,数量非常庞大。
Q: minizip 为什么无法进行目录压缩?
A: minizip 实际上阿可以压缩,不过代码开发者没有实现.
我是如何实现minizip进行目录压缩的.
下面是我的探索过程...
综合考虑,这些库都是可以商用的,最后考虑在minizip/miniuzip 基础上进行修改,增加目录项的压缩.
现象:
1. 我压缩了空文件1 , 空目录1 (用zip),发现实际上差别非常下,仅仅在entryname上有区别,前者1, 后者1\ .
2. miniuzip 在解压缩时候,实际上如果发现这是个目录名称,那么它会直接创建目录.
下面是对miniuzip 进行调试跟踪的观察.
一. 压缩了file.zip ,内部只有一个空文件1, 进行调试跟踪.
1. 打开压缩文件.
2. 查询centraldir信息从end of centraldir
2.1. 获取文件大小.
2.2. 如果文件大小小于MAX_COMMENTSIZE 那么直接读取整个文件,否则读取MAX_COMMENTSIZE。
2.3. 读取出readsize。
2.4. 从读取出的buffer中来判断0x06054b50,找出这个end of centraldir位置.
2.5. 调转到endcentralpos 读取signature code(0x06054b50)
2.6. 读取卷数,entry数量,centraldir 大小/偏移量,comment_size 等.
2.7. centralendpos -(centraloffset + centraldirsize) , 来获取centraldir对于卷开头位置的偏移量,准备读取centraldir.
3. 读取centraldir信息
3.1. 从offsetcentraldir开始读取signature(0x02014b50) .
3.2. 读取出版本号,压缩方式,日期信息,CRC,压缩大小,未压缩大小,entryname大小,file_extra_size , size_comment_file,起始卷index,internal file attr., external file attr., 当前项对于centraldir 的offset.
4. 读取entryinternal信息,比如名称,offset
5. 读取local file header 信息
5.1. 检查signature(0x04034b50) , 日期,协议中local header信息.
二. 内部空目录1, 进行调试跟踪
实际上差别仅仅在entryname,entryname length,以及由此导致的结构offset.
三. zip 压缩过程实现
对比zip在处理目录,文件都是1(空文件)的项时候实际上没有差别 ,却别仅仅是如果是目录那么最后一个字符必须是'\' or '/' ,而文件项则不是.
同上上面的测试发现,只要让minizip能够支持比如 minizip c:\1\ (c:\1\ 就可以了.
所以代码的修改在原来的代码基础上,当发现filenameinzip的最后字符是'\' or '/' 时候就放弃读取文件内容的代码,直接关闭即可.
Q : minizip如果支持目录的递归?
A: 如果用户输入了一个目录,那么minizip需要讲这个目录进行递归分解,比如 有个目录1 ,它下面有个文件叫做1234.txt 有一个目录叫做 123,而用户的输入是minizip -R c:\1 ,实际minizip内部执行了类似如下指令 minizip c:\1\ c:\1\1234.txt c:\1\123 过程就是这样,后续的继续包装完成目录递归即可.
阅读(5006) | 评论(1) | 转发(0) |