网上很多代码,都是以下的代码。我自己用SOCKET实现的时候(调用ZLIB库),发现都是可以的。
int inflate_read(char *source,int len,char **dest,int gzip)
{
int ret;
unsigned have;
z_stream strm;
unsigned char out[CHUNK];
int totalsize = 0;
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
if (gzip)
ret = inflateInit2(&strm, 47);
else
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
strm.avail_in = len;
strm.next_in = source;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
totalsize += have;
*dest = realloc(*dest,totalsize);
memcpy(*dest + totalsize - have,out,have);
} while (strm.avail_out == 0);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
而昨天用在WININET的返回数据里面的时候,发现不行。于是去搜索资料,参考了一些资料之后,发现WININET添加了gzip的头部,于是自己参考了
https://github.com/wkoszek/mini_gzip
写了一个函数。并且,miniz.c的代码里面和zlib的略不同,需要把上面一个函数的47修改成 -MZ_DEFAULT_WINDOW_BITS。
int mini_gz_get_data_offset(const unsigned char *buffer, int bufferlength)
{
int offset;
int result = 0;
if (10 < bufferlength)
{
buffer + 0; // .gz header
if (buffer[0] == 0x1F && buffer[1] == 0x8B && buffer[2] == 0x08)
{
// auxillary header
offset = 10;
if (buffer[3] & 0x4)
{
//fextra_len = buffer[offset + 1] << 8 | buffer[offset + 0];
offset += 2;
//fextra_ptr = &buffer[offset];
}
if (buffer[3] & 0x8)
{
//fname_ptr = &buffer[offset];
while (buffer[offset++] != '\0')
{
;
}
}
if (buffer[3] & 0x10)
{
//fcomment_ptr = &buffer[offset];
while (buffer[offset++] != '\0')
{
;
}
}
if (buffer[3] & 0x2)
{
//fcrc = *(unsigned short *)&buffer[offset];
offset += 2;
}
result = offset;
}
}
return (result);
}
希望后来的人可以少走弯路。