woaidongmao

文章均收录自他人博客,但不喜标题前加-[转贴],因其丑陋,见谅!~
随笔 - 1469, 文章 - 0, 评论 - 661, 引用 - 0
数据加载中……

zlib使用defalte, gzip的例子

zlib是一个比较通用的压缩库,通过在程序中引入zlib,可以方便的对数据进行压缩。今天花了点时间研究了一下,在tbuldr中实现了直接将数据库中的数据导出为gzip文件的功能。

下载zlib源代码,对于Linux,可以编译成静态库,然后将zlib.h,libz.a(如有必要,再加上zonf.h)和程序代码放置到同一个目录,编译的时候包含libz.a即可。

#./configure
#make
#make install

如果要编译成动态库,则只需要第一步改成./configure -s即可。

废话少说,下面是一段演示代码,非常简单:

#include <stdio.h>
#include "zlib.h"

int main()
{
  char *data = "this is a gzip test from NinGoo.net";
  gzFile *fp=NULL;
  fp=gzopen("test_out.gz","wb");
  gzwrite(fp,data,strlen(data));
  gzclose(fp);
}

编译:

gcc -o test test.c libz.a

执行:

$./test
$gzip -d test_out.gz
$more test_out
this is a gzip test from NinGoo.net

tbuldr中,只需要在file参数指定的文件名后面加上.gz,就会自动输出为gzip格式的文件。至此,tbuldr已基本实现了sqluldr2的全部功能,性能测试结果也不相上下了。

 

另外,zlib也可以在内存中对数据进行压缩和解压缩,参考:
http://hispider.googlecode.com/svn/trunk/devel/hispider/src/utils/zstream.c

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <zlib.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;
}

/* 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;
}

#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);
		}
	}
}
#endif

posted on 2011-06-05 03:10 肥仔 阅读(10377) 评论(3)  编辑 收藏 引用 所属分类: Windows开发

评论

# re: zlib使用defalte, gzip的例子[未登录]  回复  更多评论   

static char dummy_head[2] =
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};


static char dummy_head[2] =
{
0xB + 0x8 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};


gzip头两个固定byte不是31,120而是31,139
2013-07-15 16:24 | andy

# re: zlib使用defalte, gzip的例子[未登录]  回复  更多评论   

哦,这个dummy_head[2]计算出来的内容是{120,1}表示啥意思啊?
2013-07-15 17:05 | andy

# re: zlib使用defalte, gzip的例子[未登录]  回复  更多评论   

哦,原来是在构建zlib的头
2013-07-15 19:12 | andy

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理