deflate:使用Huffman和LZ77编码的数据压缩算法。
RFC1951:http://www.cse.ohio-state.edu/cgi-bin/rfc/rfc1951.html
zlib:是一个数据压缩格式;也是一个开源压缩库,提供deflate数据格式、zlib数据格式、gzip数据格式的压缩和解压接口。
RFC1950:http://www.cse.ohio-state.edu/cgi-bin/rfc/rfc1950.html
gzip:是一个数据压缩格式。
http://www.cse.ohio-state.edu/cgi-bin/rfc/rfc1952.html
使用deflateInit2函数,默认生成的是zlib格式的数据;按照头文件/usr/include/zlib.h里的描述,windowBits + 16,memLevel保持默认值,即可生成gzip格式数据:
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
int level,
int method,
int windowBits,
int memLevel,
int strategy));
This is another version of deflateInit with more compression options. The
fields next_in, zalloc, zfree and opaque must be initialized before by
the caller.
The method parameter is the compression method. It must be Z_DEFLATED in
this version of the library.
The windowBits parameter is the base two logarithm of the window size
(the size of the history buffer). It should be in the range 8..15 for this
version of the library. Larger values of this parameter result in better
compression at the expense of memory usage. The default value is 15 if
deflateInit is used instead.
windowBits can also be -8..-15 for raw deflate. In this case, -windowBits
determines the window size. deflate() will then generate raw deflate data
with no zlib header or trailer, and will not compute an adler32 check value.
windowBits can also be greater than 15 for optional gzip encoding. Add
16 to windowBits to write a simple gzip header and trailer around the
compressed data instead of a zlib wrapper. The gzip header will have no
file name, no extra data, no comment, no modification time (set to zero),
no header crc, and the operating system will be set to 255 (unknown). If a
gzip stream is being written, strm->adler is a crc32 instead of an adler32.
The memLevel parameter specifies how much memory should be allocated
for the internal compression state. memLevel=1 uses minimum memory but
is slow and reduces compression ratio; memLevel=9 uses maximum memory
for optimal speed. The default value is 8. See zconf.h for total memory
usage as a function of windowBits and memLevel.
The strategy parameter is used to tune the compression algorithm. Use the
value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no
string match), or Z_RLE to limit match distances to one (run-length
encoding). Filtered data consists mostly of small values with a somewhat
random distribution. In this case, the compression algorithm is tuned to
compress them better. The effect of Z_FILTERED is to force more Huffman
coding and less string matching; it is somewhat intermediate between
Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
parameter only affects the compression ratio but not the correctness of the
compressed output even if it is not set appropriately. Z_FIXED prevents the
use of dynamic Huffman codes, allowing for a simpler decoder for special
applications.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
method). msg is set to null if there is no error message. deflateInit2 does
not perform any compression: this will be done by deflate().
对于解压,头文件的描述:
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
int windowBits));
This is another version of inflateInit with an extra parameter. The
fields next_in, avail_in, zalloc, zfree and opaque must be initialized
before by the caller.
The windowBits parameter is the base two logarithm of the maximum window
size (the size of the history buffer). It should be in the range 8..15 for
this version of the library. The default value is 15 if inflateInit is used
instead. windowBits must be greater than or equal to the windowBits value
provided to deflateInit2() while compressing, or it must be equal to 15 if
deflateInit2() was not used. If a compressed stream with a larger window
size is given as input, inflate() will return with the error code
Z_DATA_ERROR instead of trying to allocate a larger window.
windowBits can also be -8..-15 for raw inflate. In this case, -windowBits
determines the window size. inflate() will then process raw deflate data,
not looking for a zlib or gzip header, not generating a check value, and not
looking for any check values for comparison at the end of the stream. This
is for use with other formats that use the deflate compressed data format
such as zip. Those formats provide their own check values. If a custom
format is developed using the raw deflate format for compressed data, it is
recommended that a check value such as an adler32 or a crc32 be applied to
the uncompressed data as is done in the zlib, gzip, and zip formats. For
most applications, the zlib format should be used as is. Note that comments
above on the use in deflateInit2() applies to the magnitude of windowBits.
windowBits can also be greater than 15 for optional gzip decoding. Add
32 to windowBits to enable zlib and gzip decoding with automatic header
detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
a crc32 instead of an adler32.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as a null strm). msg
is set to null if there is no error message. inflateInit2 does not perform
any decompression apart from reading the zlib header if present: this will
be done by inflate(). (So next_in and avail_in may be modified, but next_out
and avail_out are unchanged.)
网上的几个函数,我自己增加了一个:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <zlib.h>
#ifndef _ZSTREAM_H
#define _ZSTREAM_H
#define Z_HEADER_SIZE 12
/* Compress data */
int zcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata);
/* Uncompress data */
int zdecompress(Bytef *zdata, uLong nzdata,
Bytef *data, uLong *ndata);
/* gzip Compress data */
int gzcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata);
int httpgzcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata);
/* gzip Uncompress data */
int gzdecompress(Bytef *zdata, uLong nzdata,
Bytef *data, uLong *ndata);
/* http gzip Uncompress data */
int httpgzdecompress(Bytef *zdata, uLong nzdata,
Bytef *data, uLong *ndata);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
#include <fcntl.h>
#include <sys/stat.h>
/* Compress data */
int zcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata)
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0)
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
if(deflateInit(&c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) 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;
}
/* Compress gzip data */
int gzcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata)
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0)
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
-MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) 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;
}
int httpgzcompress(Bytef *data, uLong ndata,
Bytef *zdata, uLong *nzdata)
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0)
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
/************************************************************************
The windowBits parameter default value is 15 if deflateInit is used instead.
windowBits can also be greater than 15 for optional gzip encoding. Add16 to
windowBits to write a simple gzip header and trailer around the compressed
data instead of a zlib wrapper.
************************************************************************/
if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
31, 8, Z_DEFAULT_STRATEGY) != Z_OK) 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;
}
/* Uncompress data */
int zdecompress(Byte *zdata, uLong nzdata,
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream; /* decompression stream */
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit(&d_stream) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK) return -1;
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
/* HTTP gzip decompress */
int httpgzdecompress(Byte *zdata, uLong nzdata,
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream = {0}; /* decompression stream */
static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK )
{
if(err == Z_DATA_ERROR)
{
d_stream.next_in = (Bytef*) dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK)
{
return -1;
}
}
else return -1;
}
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
/* Uncompress gzip data */
int gzdecompress(Byte *zdata, uLong nzdata,
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream = {0}; /* decompression stream */
static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) return -1;
//if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK )
{
if(err == Z_DATA_ERROR)
{
d_stream.next_in = (Bytef*) dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK)
{
return -1;
}
}
else return -1;
}
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
//#define _DEBUG_ZSTREAM
#ifdef _DEBUG_ZSTREAM
#define BUF_SIZE 65535
int main()
{
/*char *data = "kjdalkfjdflkjdlkfjdklfjdlkfjlkdjflkdjflddajfkdjfkdfaskf;ldsfk;ldakf;ldskfl;dskf;ld";
uLong ndata = strlen(data);
Bytef zdata[BUF_SIZE];
uLong nzdata = BUF_SIZE;
Bytef odata[BUF_SIZE];
uLong nodata = BUF_SIZE;
memset(zdata, 0, BUF_SIZE);
//if(zcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)
if(gzcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)
{
fprintf(stdout, "nzdata:%d %s\n", nzdata, zdata);
memset(odata, 0, BUF_SIZE);
//if(zdecompress(zdata, ndata, odata, &nodata) == 0)
if(gzdecompress(zdata, ndata, odata, &nodata) == 0)
{
fprintf(stdout, "%d %s\n", nodata, odata);
}
}*/
int fd_in;
char *srcFile = "js.txt_gz";
char dstData[102400] = {0};
int dstDataLen = sizeof(dstData);
if((fd_in = open(srcFile,O_RDONLY)) < 0)
{
fprintf(stdout,"Error opening gzip data file.\n");
exit(-1);
}
struct stat filestat;
fstat(fd_in,&filestat);//get the file size
int dl = filestat.st_size;//
//char *srcData = (char *)malloc(dl + 1);//malloc a memory block
char srcData[102400] = {0};
//memset(srcData,0,dl + 1);//clear
int ret = 0;
if( (ret = read(fd_in,srcData,dl)) < 0)
{
fprintf(stdout,"Error reading gzip data.\n");
exit(-1);
}
fprintf(stdout,"%s\n",srcData);
if(gzdecompress((Bytef *)srcData,(uLong)dl,(Bytef *)dstData,(uLong*)&dstDataLen) == 0)
{
fprintf(stdout,"%s\n",dstData);
}
}
#endif