您的位置:首页 > 运维架构

ZLIB:gzopen与compress2函数压缩的内容有什么不同?

2011-04-13 12:37 381 查看
zlib库中,可以用compress2()函数对一块内存区域进行压缩,也可以使用gzopen()和gzwrite()两个函数将内存中的信息压缩后写入gz文件。
测试中发现,如果把compress2()函数压缩后的内容直接写成文件,这个文件无法被gzip等程序打开,可见内存压缩后的内容并不是一个标准的gz文件。
compress2()函数与gzopen()函数所产生的压缩内容到底有什么不同呢?下面是我的实验:

1、准备一个文本文件,字节数为9585字节。
2、分别使用
gzopen("test_gzopen.txt.gz", "wb9")生成文件test_gzopen.txt.gz,文件长度4152
和compress2(dst, &dst_len, src, src_len, 9)生成文件test_compress2.txt.gz,文件长度4140
3、使用二进制编辑器查看两个gz文件的内容,大部分是相同的。不同的部分为:
test_gzopen.txt.gz的前面10个字节为:
1F 8B 08 00 00 00 00 00 00 0B

test_compress2.txt.gz的前面两个字节为:
78 DA

两个文件之后的4134个字节相同

test_gzopen.txt.gz的最后8个字节为:
83 1A E0 A6 71 25 00 00

test_compress2.txt.gz的最后4个字节为:
44 75 8B EF

4、gzip文件头中,1F 8B为GZIP文件的MAGIC NUMBER
gzip文件的最后四个字节是文件的长度,Hex(71 25 00 00)=Dec(9585)
gzip文件的倒数第五到第八个字节是CRC32校验码

5、参考了一篇关于zlib的文章:http://blog.developers.api.sina.com.cn/?tag=zlib
猜想gzip文件的文件头大约是这个含义
struct GzipHeader
{
char Id1; //1f
char Id2; //8b
char cm; //08 Z_DEFLATED
char flag; //00
char mime[4]; //00 00 00 00
char xfl; //00
char os; //0B 11-windows
};

结论:
可见,compress2()函数与gzopen()函数所产生的数据的压缩内容是相同的,仅仅只是产生的头不同而已。
本来想写一个函数,将compress2()的压缩结果在内存中形成gzip的格式,但是校验码的问题一直搞不定,暂时未找到校验码是如何计算得出的,希望有这方面知识的朋友给我予指点,谢谢。

后记:
研究zlib的目的,是想要自己实现一个简易的HTTP服务器,需要在HTTP服务器中实现内容的压缩下载。
在返回的HTTP头中加上Content-Encoding: deflate或Content-Encoding: gzip就可以对相应的内容部分进行压缩输出。
由于暂时没办法将compress2()函数压缩的结果转换为gzip格式,又不能使用gzopen()函数将数据压缩成文件再输出(IO操作一定很慢)。研究了一下发现,其实很容易解决:将HTTP头指定为deflate,将compress2()函数的压缩结果输出为:send(sock, buffer+2, compress_len-6)就实现了deflate方式的压缩。

==========================
参考: http://www.zlib.net/ zlib Home Site http://blog.developers.api.sina.com.cn/?tag=zlib 18个字节: gzip 与 deflate

========================================================
2009-04-02:补充
今天测试发现,使用deflate压缩方式,不能只输出压缩的数据部分,正确的输出方式应该是:
send(sock, buffer+2, compress_len-2)
也就是说仅仅去掉compress2()压缩后的前面两个字节,最后的四个字节不能去掉,否则发送到客户端的内容虽然能够正确显示,但是最后几个字节显示不出来。
所以deflate压缩方式应该只比gzip压缩方式少14字节,而不是18个字节。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: