这个代码在http://www.j286.com/有更新详情访问。
好吧~我承认..我是为了写博文在拆分工程- -!!!
在想要对gzip进行解压之前请确定你的数据是否需要做这个处理http://www.cnblogs.com/dsblab/articles/2328890.html
HTTP 头中标识数据经过gzip的如上面第二个框。
对gzip的处理我们可以用强大的zlib库进行处理
C语言的zlib编译
http://www.cnblogs.com/dsblab/articles/2328883.html
http://www.cnblogs.com/dsblab/articles/2328880.html
我不是在推销...没这你做不下去,如果你是linux下作开发的话编译应该那应该是小菜了。
在使用前需要包含相关文件和库
#include "zlib/zlib.h"#pragma comment(lib, "zlib.lib")
当然解压数据长度你可以分配一个稍微大一些的空间来存储再realloc还是索性一个大数组,或者用其他zlib提供的函数就出在分配,这个要看你自己了。
注意,使用的时候不要把头文件穿进去,把DATA段传进去就行了,否则会怎么样我不知道。。。没试过C#的stream
1 /* HTTP gzip decompress */ 2 /* 参数1.压缩数据 2.数据长度 3.解压数据 4.解压后长度 */ 3 int httpgzdecompress(Byte *zdata, uLong nzdata, Byte *data, uLong *ndata) 4 { 5 int err = 0; 6 z_stream d_stream = {0}; /* decompression stream */ 7 static char dummy_head[2] = 8 { 9 0x8 + 0x7 * 0x10,10 (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,11 };12 d_stream.zalloc = (alloc_func)0;13 d_stream.zfree = (free_func)0;14 d_stream.opaque = (voidpf)0;15 d_stream.next_in = zdata;16 d_stream.avail_in = 0;17 d_stream.next_out = data;18 if(inflateInit2(&d_stream, 47) != Z_OK) return -1;19 while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) 20 {21 d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */22 if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;23 if(err != Z_OK )24 {25 if(err == Z_DATA_ERROR)26 {27 d_stream.next_in = (Bytef*) dummy_head;28 d_stream.avail_in = sizeof(dummy_head);29 if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 30 {31 return -1;32 }33 }34 else return -1;35 }36 }37 if(inflateEnd(&d_stream) != Z_OK) return -1;38 *ndata = d_stream.total_out;39 return 0;40 }如果对平台没要求的话还是建议用C#来做好了,省力省时
HttpWebResponse getRespone = (HttpWebResponse)get.GetResponse();if (getRespone != null && getRespone.StatusCode == HttpStatusCode.OK) { recv = getRespone.ContentEncoding; System.IO.Stream resStream = getRespone.GetResponseStream();if (recv == "gzip") { resStream = new GZipStream(resStream, CompressionMode.Decompress); } System.IO.StreamReader sr = new System.IO.StreamReader(resStream, Encoding.UTF8); recv = sr.ReadToEnd(); sr.Close(); } getRespone.Close();C语言不像C#一样有很多很多高度的模块化的东西可以使用,在通讯过程中特别是与http相关的通讯过程中可能要对网站返回的数据做一定处理,而且有不少网站的回应是强制性的,例如向网站请求deflate有个能会返回的是gzip的数据。在这过程中与web特性有关的,在服务器构造消息之前可能并不知道或者不方便知道消息的长度,于是就会将消息分为一段段进行传送。
例如如下回应:
不难发现,chunked正式实现这一思想的方式。
每个HTTP头部含有Transfer-Encoding: chunked则表明此包Data是分块传输的。关于他的介绍痿基百科上说的很多,有兴趣可以看看http://en.wikipedia.org/wiki/Chunked_transfer_encoding
实质上我们做的工作就是要对HTTP返回的头部含有Transfer-Encoding: chunked的数据做解码工作。
数据结构如下:长度[HEX]\r\n内容\r\n长度[HEX]\r\n内容\r\n\0\r\n\r\n
解码过程当然很简单,没涉及任何数学知识,或者更本谈不上解码,知识做合并工作罢了。。。
C语言能用的找了10分钟百度不到,除了一段满是奇怪参缺少函数的数狗啃的,索性干脆自己写一个算了。。。
以下是C(C++)实现代码,在1块长度112下测试通过,应该没什么BUG。有的话烦请只出,代码应该算得上严谨了。
1 /* 2 * 十六进制表示的字符串转换为相应的十进制值 传入"7f"返回127 3 */ 4 int htoi(unsigned char *s) 5 { 6 int i; 7 int n = 0; 8 if (s[0] == '0' && (s[1]=='x' || s[1]=='X')) //判断是否有前导0x或者0X 9 { 10 i = 2; 11 } 12 else 13 { 14 i = 0; 15 } 16 for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') || (s[i] >='A' && s[i] <= 'Z');++i) 17 { 18 if (tolower(s[i]) > '9') 19 { 20 n = 16 * n + (10 + tolower(s[i]) - 'a'); 21 } 22 else 23 { 24 n = 16 * n + (tolower(s[i]) - '0'); 25 } 26 } 27 return n; 28 } 29 30 /*31 * 查找关键数据串在长数据中出现的位置32 * 参数:1长数据指针,2搜索最大长度,3关键字指针,4关键字长度,5搜索起始位置(返回出现位置,若未找到则不变)33 * 返回:返回1 成功 返回 0 未找到34 */35 int _find_key(unsigned char *data,int data_length,unsigned char *key,int key_length,int *position)36 {37 int i = *position;38 if(key == NULL || i<0)39 {40 return 0;41 }42 for(; i <= data_length-key_length; i++)43 {44 if( memcmp(data+i, key, key_length) == 0 )45 {46 *position = i;47 return 1;48 }49 }50 return 0;51 }52 53 /*54 * 对HTTP的chunked消息进行合块55 * 参数:1待处理数据,2数据长度(分配的长度即可,不一定要求出实际有效长度),3返回合块后的数据,4合块长度56 * 算法具有前驱性,返回和传入data可以是同一块内存区域(不建议)57 */58 int de_chunked(unsigned char *data,int data_length,unsigned char *dest,int *dest_length)59 {60 char chunked_hex[CHUNKED_MAX_LEN + 1]; // 十六进制的块长度61 int chunked_len; // 块长度62 int ret;63 int begin = 0;64 int end = 0;65 int i = 0;66 int index = 0;67 68 ret = _find_key(data,data_length,"0\r\n\r\n",5,&end);69 if (ret == 0) //信息不完整70 return 0;71 72 ret = _find_key(data,data_length,"\r\n\r\n",4,&begin);73 begin = begin + 4; //移动到数据起点74 75 while(memcmp(data+begin,"0\r\n\r\n",5) != 0)76 {77 //获得当前块长度78 ret = _find_key(data+begin,CHUNKED_MAX_LEN,"\r\n",2,&i);79 if (ret == 0) //信息不完整80 return 0;81 memcpy(chunked_hex,data+begin,i);82 chunked_hex[i] = '\0';83 chunked_len = htoi(chunked_hex);84 //移动到当前块数据段85 begin = begin + i + 2;86 //获得当前块数据87 if (memcmp(data+begin+chunked_len,"\r\n",2) != 0)88 return 0; //信息有误89 memcpy(dest+index,data+begin,chunked_len);90 index = index + chunked_len;91 //移动到下一块块长度92 begin = begin + chunked_len + 2;93 i = begin;94 if(begin > end) //结构错误95 return -1;96 }97 *dest_length = index;98 return 1;99 }
转载于:https://www.cnblogs.com/stlong/p/6289086.html
相关资源:数据结构—成绩单生成器