关闭

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

标签: http服务器bufferdst测试structhex
2597人阅读 评论(3) 收藏 举报
分类:
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个字节。
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:593426次
    • 积分:6582
    • 等级:
    • 排名:第3591名
    • 原创:71篇
    • 转载:301篇
    • 译文:1篇
    • 评论:27条
    文章分类
    最新评论