免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4033 | 回复: 7

[函数] zlib inflate函数解压缩gzip数据总是失败 [复制链接]

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
发表于 2016-04-13 16:15 |显示全部楼层
本帖最后由 qianguozheng 于 2016-04-13 16:16 编辑

网上找了很多解压缩到例子,法总总是Z_DATA_ERROR,不知道是什么原因。

目的是解压缩http gzip压缩到body, 我获取利body,通过gzip -d xxx.gz可以解压, 但是我的程序就是不行。
希望大神能帮忙看看哪里出问题了。

测试用到test.gz已经上传到附件。
程序代码如下:


  1. #include <zlib.h>
  2. #include <string>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <zlib.h>

  9. using namespace std;

  10. class CUncompress
  11. {
  12.        
  13. public:
  14.         CUncompress(string & sUncompressData);
  15.         ~CUncompress();
  16. public:
  17.         int Init(const char * pszCompressed, int nCompressedLen, bool bIsGzip=false);
  18.         int UncompressData();
  19.         char * GetErrMsg()
  20.         {
  21.                 return m_szErrMsg;
  22.         }
  23. private:
  24.         string & m_sData;
  25.         char * m_pszDataChunk;
  26.         z_stream m_objStream;
  27.         char m_szErrMsg[1024];
  28.         bool m_bIsGzip;
  29.        
  30. };

  31. //-----------CPP

  32. static const int DSIZE = 0x10000;

  33. CUncompress::CUncompress(string & sUncompressData):m_sData(sUncompressData)
  34. {
  35.         memset(m_szErrMsg, 0, 1024);
  36.         m_pszDataChunk = new char[DSIZE];
  37.         m_bIsGzip = false;
  38. }

  39. CUncompress::~CUncompress()
  40. {
  41.         if (m_pszDataChunk != NULL)
  42.         {
  43.                 delete [] m_pszDataChunk;
  44.         }
  45. }

  46. int CUncompress::Init(const char * pszCompressed, int nCompressedLen, bool bIsGzip)
  47. {
  48.         int nErrCode = 0;
  49.         m_objStream.zalloc = (alloc_func)Z_NULL;
  50.         m_objStream.zfree = (free_func)Z_NULL;
  51.         m_objStream.opaque = 0;
  52.         m_objStream.next_in = NULL;
  53.         m_objStream.avail_in = 0;
  54.         if (bIsGzip)
  55.         {
  56.                 m_bIsGzip = true;
  57.                 if (strcmp(zlibVersion(), "1.2.0.4") < 0)
  58.                 {
  59.                         snprintf(m_szErrMsg, 1024, "zlib version < 1.2.0.4");
  60.                         return -1;
  61.                 }
  62.                 //if ((nErrCode = inflateInit2(&m_objStream, MAX_WBITS + 32)) != Z_OK)
  63.                 if ((nErrCode = inflateInit2(&m_objStream, 31)) != Z_OK)
  64.                 {
  65.                         snprintf(m_szErrMsg, 1024, "inflateInit2 failed, err code=%d", nErrCode);
  66.                         return -2;
  67.                 }
  68.         }
  69.         else
  70.         {
  71.                 if ((nErrCode = inflateInit(&m_objStream)) != Z_OK)
  72.                 {
  73.                         snprintf(m_szErrMsg, 1024, "inflateInit failed, err code=%d", nErrCode);
  74.                         return -3;
  75.                 }
  76.         }
  77.         m_objStream.next_in = (Bytef*)pszCompressed;
  78.         m_objStream.avail_in = (uInt)nCompressedLen;
  79.         return 0;
  80. }

  81. int CUncompress::UncompressData()
  82. {
  83.         bool bRetry = true;
  84.         uInt unRead = m_objStream.avail_in;
  85.         Bytef * pszInData = m_objStream.next_in;
  86.         int nStatus = 0;
  87.         for (;;)
  88.         {
  89.                 m_objStream.next_out = (Bytef*)m_pszDataChunk;
  90.                 m_objStream.avail_out = DSIZE;
  91.                 nStatus = inflate(&m_objStream, Z_SYNC_FLUSH);
  92.                 if (nStatus == Z_OK || nStatus == Z_STREAM_END)
  93.                 {
  94.                         bRetry = false;
  95.                         if (DSIZE - m_objStream.avail_out)
  96.                         {
  97.                                 m_sData.append(m_pszDataChunk, DSIZE - m_objStream.avail_out);
  98.                         }
  99.                         if (nStatus == Z_STREAM_END || (nStatus == Z_OK && m_objStream.avail_in == 0))
  100.                         {
  101.                                 if ((nStatus = inflateEnd(&m_objStream)) == Z_OK)
  102.                                 {
  103.                                         return 0;
  104.                                 }
  105.                                 else
  106.                                 {
  107.                                         snprintf(m_szErrMsg, 1024, "inflateEnd failed, err code=%d", nStatus);
  108.                                         return -1;
  109.                                 }
  110.                         }
  111.                 }
  112.                 else if ((!m_bIsGzip) && bRetry && nStatus == Z_DATA_ERROR)
  113.                 {
  114.                         //if has no zlib header, try another way
  115.                         (void)inflateEnd(&m_objStream);
  116.                         if ((nStatus = inflateInit2(&m_objStream, -MAX_WBITS)) != Z_OK)
  117.                         {
  118.                                 snprintf(m_szErrMsg, 1024, "data has no zlib header, try another way inflateInit2 failed, err cod=%d", nStatus);
  119.                                 return -2;
  120.                         }
  121.                         m_objStream.next_in = pszInData;
  122.                         m_objStream.avail_in = unRead;
  123.                         bRetry = false;
  124.                         continue;
  125.                 }
  126.                 else
  127.                 {
  128.                         (void)inflateEnd(&m_objStream);
  129.                         snprintf(m_szErrMsg, 1024, "error when inflate compressed, err code=%d", nStatus);
  130.                         return -3;
  131.                 }
  132.         }
  133.         return 0;
  134. }



  135. /* Uncompress gzip data */
  136. /* zdata 数据 nzdata 原数据长度 data 解压后数据 ndata 解压后长度 */
  137. int gzdecompress(Byte *zdata, uLong nzdata,
  138.                  Byte *data, uLong *ndata)
  139. {
  140.     int err = 0;
  141.     z_stream d_stream = {0}; /* decompression stream */
  142.     static char dummy_head[2] = {
  143.         0x8 + 0x7 * 0x10,
  144.         (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
  145.     };
  146.     d_stream.zalloc = NULL;
  147.     d_stream.zfree = NULL;
  148.     d_stream.opaque = NULL;
  149.     d_stream.next_in  = zdata;
  150.     d_stream.avail_in = 0;
  151.     d_stream.next_out = data;
  152.     //只有设置为MAX_WBITS + 16才能在解压带header和trailer的文本
  153.     if(inflateInit2(&d_stream, MAX_WBITS + 16) != Z_OK) return -1;
  154.     //if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
  155.     while(d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
  156.         d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
  157.         if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
  158.         if(err != Z_OK) {
  159.             if(err == Z_DATA_ERROR) {
  160.                 d_stream.next_in = (Bytef*) dummy_head;
  161.                 d_stream.avail_in = sizeof(dummy_head);
  162.                 if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) {
  163.                                         std::cout<<"Fuck"<<std::endl;
  164.                     return -1;
  165.                 }
  166.             } else{
  167.                                 std::cout<<"Fuckxxx"<<std::endl;
  168.                                  return -1;
  169.                          }
  170.         }
  171.     }
  172.     if(inflateEnd(&d_stream) != Z_OK) return -1;
  173.     *ndata = d_stream.total_out;
  174.     return 0;
  175. }

  176. char *decompress(char *compressed, int wsize, int input_len, int bufsize)
  177. {
  178.         printf("wsize=%d, input_len=%d, bufsize=%d\n", wsize, input_len, bufsize);
  179.     Byte *result_str;
  180.     Byte *input = (Byte *)compressed;
  181.     int length, err;
  182.     //int wsize=DEF_WBITS;
  183.     //Py_ssize_t r_strlen=DEFAULTALLOC;
  184.     int r_strlen = bufsize;
  185.     length = input_len;
  186.     z_stream zst;

  187.     //if (!PyArg_ParseTuple(args, "s#|in:decompress",
  188.     //                      &input, &length, &wsize, &r_strlen))
  189.     //    return NULL;

  190.     if (r_strlen <= 0)
  191.         r_strlen = 1;

  192.     zst.avail_in = length;
  193.     zst.avail_out = r_strlen;

  194.     //if (!(result_str = PyString_FromStringAndSize(NULL, r_strlen)))
  195.     //    return NULL;
  196.     result_str = (Byte *)malloc(r_strlen);
  197.         memset(result_str, 0, r_strlen)
  198.         ;
  199.     zst.zalloc = (alloc_func)NULL;
  200.     zst.zfree = (free_func)Z_NULL;
  201.     zst.next_out = (Byte *)(result_str);
  202.     zst.next_in = (Byte *)input;
  203.     err = inflateInit2(&zst, wsize);

  204.     switch(err) {
  205.     case(Z_OK):
  206.         break;
  207.     case(Z_MEM_ERROR):
  208.         //PyErr_SetString(PyExc_MemoryError,
  209.         printf("Out of memory while decompressing data\n");
  210.         goto error;
  211.     default:
  212.         inflateEnd(&zst);
  213.         //zlib_error(zst, err, "while preparing to decompress data");
  214.         printf("while preparing to decompress data\n");
  215.         goto error;
  216.     }

  217.     do {
  218.         //Py_BEGIN_ALLOW_THREADS
  219.         //err=inflate(&zst, Z_FINISH);
  220.         
  221.         err=inflate(&zst, Z_SYNC_FLUSH);
  222.         //Py_END_ALLOW_THREADS
  223.                 printf(" inflate: err=%d\n", err);
  224.         switch(err) {
  225.         case(Z_STREAM_END):
  226.             break;
  227.         case(Z_BUF_ERROR):
  228.             /*
  229.              * If there is at least 1 byte of room according to zst.avail_out
  230.              * and we get this error, assume that it means zlib cannot
  231.              * process the inflate call() due to an error in the data.
  232.              */
  233.             if (zst.avail_out > 0) {
  234.                 //zlib_error(zst, err, "while decompressing data");
  235.                 printf("while decompressing data\n");
  236.                 inflateEnd(&zst);
  237.                 goto error;
  238.             }
  239.             /* fall through */
  240.         case(Z_OK):
  241.             /* need more memory */
  242.             /*if (_PyString_Resize(&result_str, r_strlen << 1) < 0) {
  243.                 inflateEnd(&zst);
  244.                 goto error;
  245.             }*/
  246.             //zst.next_out = (unsigned char *)PyString_AS_STRING(result_str)
  247.             zst.next_out = (unsigned char *)(result_str) \
  248.                 + r_strlen;
  249.             zst.avail_out = r_strlen;
  250.             r_strlen = r_strlen << 1;
  251.             break;
  252.         default:
  253.             inflateEnd(&zst);
  254.             //zlib_error(zst, err, "while decompressing data");
  255.             printf("%d: while decompressing data, %d\n", __LINE__, err);
  256.             goto error;
  257.         }
  258.     } while (err != Z_STREAM_END);

  259.     err = inflateEnd(&zst);
  260.     if (err != Z_OK) {
  261.         //zlib_error(zst, err, "while finishing data decompression");
  262.         printf("while finishing data decompression\n");
  263.         goto error;
  264.     }

  265.     //_PyString_Resize(&result_str, zst.total_out);
  266.     //global_decompress_err = err;
  267.     return (char *)result_str;

  268. error:
  269.     //Py_XDECREF(result_str);
  270.     if (result_str)
  271.     {
  272.                 free(result_str);
  273.         }
  274.     return NULL;
  275. }

  276. int main(int argc, char *argv[])
  277. {
  278.        
  279.         std::ifstream f1;
  280.         std::string buffer;
  281.        
  282.         f1.open("test.gz");
  283.        
  284.         if(!f1)
  285.         {
  286.                 std::cout <<"open test.gz file failed"<<std::endl;
  287.                 return 0;
  288.         }
  289.        
  290.         char c[80];
  291.         char buf[30000];
  292.         memset(buf, 0, sizeof(buf));
  293.         int len = 0;
  294.         while(!f1.eof())
  295.         {
  296.                 f1.read(c,80);
  297.        
  298.                 //std::string str(c);
  299.                 //buffer += str;
  300.                 len += f1.gcount();
  301.                 std::cout<<"len="<<len<<" bufsize="<<buffer.size()<<std::endl;
  302.                 memcpy(buf, c, f1.gcount());
  303.         }
  304.         f1.close();

  305.         //std::cout<<"buffer size="<<buffer.size()<<std::endl;
  306.        
  307. #if 0
  308.         std::string uncompress;
  309.         CUncompress dcp(uncompress);
  310.         //CUncompress::Init(char * pszCompressed, int nCompressedLen, bool bIsGzip)
  311.        
  312.         dcp.Init((const char *)buf, len, true);
  313.         dcp.UncompressData();
  314.         std::cout<<"Error:"<<dcp.GetErrMsg()<<std::endl;
  315.        
  316.         std::cout<<"Uncompressed Data="<<uncompress<<std::endl;
  317.        
  318.         char rawdata[1200000];
  319.         int rawlen = 1200000;
  320.         gzdecompress((Byte *)buf, len, (Byte *)rawdata, (long unsigned int*) &rawlen);
  321.         std::cout<<"raw data="<<rawdata<<std::endl;
  322. #else

  323.         // char *decompress(char *compressed, int wsize, int input_len, int bufsize)
  324.         char *result = NULL;
  325.        
  326.         result = decompress(buf, MAX_WBITS+16, len, 1200000);
  327.         printf("result=%s", result);
  328.        
  329. #endif
  330.        
  331. }

复制代码
test.gz (20.6 KB, 下载次数: 6)

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
发表于 2016-04-13 16:17 |显示全部楼层
网上找到了两三个函数, 测试都不行

论坛徽章:
133
操作系统版块每日发帖之星
日期:2016-05-11 17:06:57操作系统版块每日发帖之星
日期:2016-05-11 17:06:57数据库技术版块每日发帖之星
日期:2016-05-11 17:07:05操作系统版块每日发帖之星
日期:2016-05-11 17:06:57操作系统版块每日发帖之星
日期:2016-05-11 17:06:57综合交流区版块每日发帖之星
日期:2016-05-11 17:07:052022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:57IT运维版块每日发帖之星
日期:2016-05-11 17:06:49操作系统版块每日发帖之星
日期:2016-05-11 17:06:57综合交流区版块每日发帖之星
日期:2016-05-11 17:07:05操作系统版块每日发帖之星
日期:2016-05-11 17:06:57程序设计版块每日发帖之星
日期:2016-05-11 17:06:57
发表于 2016-04-13 18:20 |显示全部楼层
没必要压缩,真正吃流量的是图片视频,你还压缩不鸟

文字这些又不伤多少流量的

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
发表于 2016-04-22 17:31 |显示全部楼层
回复 3# shang2010


    没人要压缩,这是解压缩,看清问题再回答。 搞定了。

论坛徽章:
133
操作系统版块每日发帖之星
日期:2016-05-11 17:06:57操作系统版块每日发帖之星
日期:2016-05-11 17:06:57数据库技术版块每日发帖之星
日期:2016-05-11 17:07:05操作系统版块每日发帖之星
日期:2016-05-11 17:06:57操作系统版块每日发帖之星
日期:2016-05-11 17:06:57综合交流区版块每日发帖之星
日期:2016-05-11 17:07:052022北京冬奥会纪念版徽章
日期:2015-08-07 17:10:57IT运维版块每日发帖之星
日期:2016-05-11 17:06:49操作系统版块每日发帖之星
日期:2016-05-11 17:06:57综合交流区版块每日发帖之星
日期:2016-05-11 17:07:05操作系统版块每日发帖之星
日期:2016-05-11 17:06:57程序设计版块每日发帖之星
日期:2016-05-11 17:06:57
发表于 2016-04-22 21:43 |显示全部楼层
看你代码写得蛮多的,感觉还是高级语言方便,
c/cpp太复杂了

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
发表于 2016-05-11 15:26 |显示全部楼层
回复 5# shang2010


    写多了就习惯了,早就想搞高级语言了,没人腰阿

论坛徽章:
9
程序设计版块每日发帖之星
日期:2015-10-18 06:20:00程序设计版块每日发帖之星
日期:2015-11-01 06:20:00程序设计版块每日发帖之星
日期:2015-11-02 06:20:00每日论坛发贴之星
日期:2015-11-02 06:20:00程序设计版块每日发帖之星
日期:2015-11-03 06:20:00程序设计版块每日发帖之星
日期:2015-11-04 06:20:00程序设计版块每日发帖之星
日期:2015-11-06 06:20:00数据库技术版块每周发帖之星
日期:2015-12-02 15:02:47数据库技术版块每日发帖之星
日期:2015-12-08 06:20:00
发表于 2016-05-17 08:35 |显示全部楼层
本帖最后由 wlmqgzm 于 2016-05-17 08:35 编辑

回复 4# qianguozheng

怎么搞定的?  我猜是文件开头的几个字节不同, 就是文件方式前面有增加的额外的特殊字段(用于说明文件一些属性的).


   

论坛徽章:
7
IT运维版块每日发帖之星
日期:2016-05-27 06:20:00IT运维版块每日发帖之星
日期:2016-06-09 06:20:00操作系统版块每日发帖之星
日期:2016-06-12 06:20:00程序设计版块每日发帖之星
日期:2016-06-12 06:20:00操作系统版块每日发帖之星
日期:2016-06-13 06:20:00IT运维版块每日发帖之星
日期:2016-06-17 06:20:002015-2016NBA季后赛纪念章
日期:2016-06-28 17:42:27
发表于 2016-05-23 11:03 |显示全部楼层
回复 7# wlmqgzm


    我上面的代码就可以正常解压缩。 测试失败的原因是我的读取函数有问题。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会,7折限时优惠重磅来袭!
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。

限时七折期:2019年8月31日前


----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:huangweiwei@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP