#include <zlib.h>
#include <iostream>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
#define RD_GZ_CHUNK 262144
#define RD_ZERO_INIT {0}
/* Compress gzip data */
/* data 原数据 ndata 原数据长度 zdata 压缩后数据 nzdata 压缩后长度 */
int gzcompress( Bytef *data, uLong ndata,
Bytef *zdata, uint64_t *nzdata )
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0)
{
c_stream.zalloc = NULL;
c_stream.zfree = NULL;
c_stream.opaque = NULL;
int iRet = -1;
//只有设置为MAX_WBITS + 16才能在在压缩文本中带header和trailer
if ( iRet = deflateInit2( &c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY ) != Z_OK )
{
cout << "deflateInit2 return " << iRet << endl;
return -1;
}
c_stream.next_in = data;
c_stream.avail_in = ndata;
c_stream.next_out = zdata;
c_stream.avail_out = *nzdata;
while(c_stream.avail_in != 0 && c_stream.total_out < *nzdata)
{
if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;
}
if(c_stream.avail_in != 0)
return c_stream.avail_in;
for(;;)
{
if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END)
break;
if(err != Z_OK)
return -1;
}
if(deflateEnd(&c_stream) != Z_OK)
return -1;
*nzdata = c_stream.total_out;
return 0;
}
return -1;
}
char * rd_gz_decompress ( const char *compressed, int compressed_len,
uint64_t *decompressed_lenp )
{
int pass = 1;
char *decompressed = NULL;
/* First pass (1): calculate decompressed size.
* (pass-1 is skipped if *decompressed_lenp is
* non-zero).
* Second pass (2): perform actual decompression.
*/
if (*decompressed_lenp != 0LLU)
pass++;
for (; pass <= 2 ; pass++)
{
z_stream strm = RD_ZERO_INIT;
gz_header hdr;
char buf[512];
char *p;
int len;
int r;
if ((r = inflateInit2(&strm, 15+32)) != Z_OK)
goto fail;
strm.next_in = (Bytef *)compressed;
strm.avail_in = compressed_len;
if ((r = inflateGetHeader(&strm, &hdr)) != Z_OK)
{
inflateEnd(&strm);
goto fail;
}
if (pass == 1)
{
/* Use dummy output buffer */
p = buf;
len = sizeof(buf);
}
else
{
/* Use real output buffer */
p = decompressed;
len = (int)*decompressed_lenp;
}
do
{
strm.next_out = (unsigned char *)p;
strm.avail_out = len;
r = inflate(&strm, Z_NO_FLUSH);
switch (r)
{
case Z_STREAM_ERROR:
case Z_NEED_DICT:
case Z_DATA_ERROR:
case Z_MEM_ERROR:
inflateEnd(&strm);
goto fail;
}
if (pass == 2)
{
/* Advance output pointer (in pass 2). */
p += len - strm.avail_out;
len -= len - strm.avail_out;
}
} while (strm.avail_out == 0 && r != Z_STREAM_END);
if (pass == 1)
{
*decompressed_lenp = strm.total_out;
if (!(decompressed = (char*)malloc((size_t)(*decompressed_lenp)+1)))
{
inflateEnd(&strm);
return NULL;
}
/* For convenience of the caller we nul-terminate
* the buffer. If it happens to be a string there
* is no need for extra copies. */
decompressed[*decompressed_lenp] = '\0';
}
inflateEnd(&strm);
}
return decompressed;
fail:
if (decompressed)
free(decompressed);
return NULL;
}
int main( int argc, char ** argv )
{
int iRet = -1;
char sBuffer[65536];
memset( sBuffer, 0, sizeof( sBuffer ) );
char * sOriginal = "Hello world!123456789001234567890123456789012345678901234567890";
// compress it
uint64_t iCompressedLen = sizeof(sBuffer);
gzcompress( (Bytef*)sOriginal, strlen( sOriginal ),
(Bytef*)sBuffer, &iCompressedLen );
cout << "sOriginal:" << sOriginal << ",iCompressedLen:"
<< iCompressedLen << endl;
uint64_t iDecompressedLen = 0;
char *decompressed = (char*)rd_gz_decompress ( sBuffer,
iCompressedLen, &iDecompressedLen );
if ( decompressed != NULL )
{
cout << "after decrypt is " << decompressed
<< ", iDecompressedLen is " << iDecompressedLen << endl;
}
else
{
cout << "rd_gz_decompress failed." << endl;
}
return iRet;
}
make.sh
g++ main.cpp -lz
sh -x make.sh
./a.out
sOriginal:Hello world!123456789001234567890123456789012345678901234567890,iCompressedLen:46
after decrypt is Hello world!123456789001234567890123456789012345678901234567890, iDecompressedLen is 63