zlib库compress和uncompress函数

1、compress函数

/*
     Compresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer. Upon entry, destLen is the total
   size of the destination buffer, which must be at least the value returned
   by compressBound(sourceLen). Upon exit, destLen is the actual size of the
   compressed buffer.
     This function can be used to compress a whole file at once if the
   input file is mmap'ed.
     compress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer.
*/

int compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
        compress函数将 source 缓冲区中的内容压缩到 dest 缓冲区。 sourceLen 表示source 缓冲区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLen表示 dest 缓冲区的大小,zlib本身有提供compressBound函数用于计算压缩后缓冲区长度的上限值,不需要额外再设计一些不适当的预测算法(注意2002年的版本没有compressBound函数,2004年及以后的版本都是有的)。当函数退出后,destLen 表示压缩后缓冲区的实际大小。此时 destLen / sourceLen 正好是压缩率。
        若compress 若成功,则返回 Z_OK;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。
 

2、uncompress函数

/*
     Decompresses the source buffer into the destination buffer.  sourceLen is
   the byte length of the source buffer. Upon entry, destLen is the total
   size of the destination buffer, which must be large enough to hold the
   entire uncompressed data. (The size of the uncompressed data must have
   been saved previously by the compressor and transmitted to the decompressor
   by some mechanism outside the scope of this compression library.)
   Upon exit, destLen is the actual size of the compressed buffer.
     This function can be used to decompress a whole file at once if the
   input file is mmap'ed.
 
     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
   enough memory, Z_BUF_ERROR if there was not enough room in the output
   buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete.
*/
int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);
uncompress 函数将 source 缓冲区的内容解压缩到 dest 缓冲区。sourceLen 是 source 缓冲区的大小(以字节计)。注意函数的第二个参数 destLen 是传址调用。当调用函数时,destLen 表示 dest 缓冲区的大小, dest 缓冲区要足以容下解压后的数据。在进行解压缩时,需要提前知道被压缩的数据解压出来会有多大。这就要求在进行压缩之前,保存原始数据的大小(也就是解压后的数据的大小)。这不是 zlib 函数库的功能,需要我们做额外的工作。当函数退出后, destLen 是解压出来的数据的实际大小。
        若uncompress 若成功,则返回 Z_OK ;若没有足够内存,则返回 Z_MEM_ERROR;若输出缓冲区不够大,则返回 Z_BUF_ERROR。若输入数据有误,则返回 Z_DATA_ERROR。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <zlib.h>

int main(int argc, char* argv[])
{
	char text[] = "zlib compress and uncompress test\[email protected]\n2012-11-05\n";
	uLong tlen = strlen(text) + 1;	/* 需要把字符串的结束符'\0'也一并处理 */
	char* buf = NULL;
	uLong blen;
 
	/* 计算缓冲区大小,并为其分配内存 */
	blen = compressBound(tlen);	/* 压缩后的长度是不会超过blen的 */
	if((buf = (char*)malloc(sizeof(char) * blen)) == NULL)
	{
		printf("no enough memory!\n");
		return -1;
	}
 
	/* 压缩 */
	if(compress(buf, &blen, text, tlen) != Z_OK)
	{
		printf("compress failed!\n");
		return -1;
	}
 
	/* 解压缩 */
	if(uncompress(text, &tlen, buf, blen) != Z_OK) 
	{
		printf("uncompress failed!\n");
		return -1;
	}
 
	/* 打印结果,并释放内存 */
	printf("%s", text);
	if(buf != NULL)
	{
		free(buf);
		buf = NULL;
	}
 
	return 0;
}

zlib处理的对象是Bytef*字节流,很多人遇到字符串就会混淆了,其实很简单,字节流是没有结束符的,需要配备长度信息,所以处理字符串的时候需要把结束符也当成一个普通的字节,这样计算长度的时候也需要算它一份。

另外绝大部分人都想动态分配缓冲区,也就是说需要多少再给多少,其实zlib本身有提供compressBound函数用于计算压缩后缓冲区长度的上限值,不需要额外再设计一些不适当的预测算法,不过解压缩的时候没有提供长度的预测,由于compress和uncompress一般都是成对使用的,预先保存好原文的长度即可。

#include <cstring>
#include <cstdlib>
#include <iostream>
#include "zlib.h"
 
using namespace std;
 
int main()
{
    int err;
    Byte compr[200], uncompr[200];    // big enough
    uLong comprLen, uncomprLen;
 
    const char* hello = "12345678901234567890123456789012345678901234567890";
    uLong len = strlen(hello) + 1;
    comprLen  = sizeof(compr) / sizeof(compr[0]);
 
    err = compress(compr, &comprLen, (const Bytef*)hello, len);
    if (err != Z_OK) 
    {
        cerr << "compess error: " << err << '\n';
        exit(1);
    }
 
    cout << "orignal size: " << len
         << " , compressed size : " << comprLen << '\n';
 
    strcpy((char*)uncompr, "garbage");
 
    err = uncompress(uncompr, &uncomprLen, compr, comprLen);
    if (err != Z_OK) 
    {
        cerr << "uncompess error: " << err << '\n';
        exit(1);
    }
 
    cout << "orignal size: " << len
         << " , uncompressed size : " << uncomprLen << '\n';
 
    if (strcmp((char*)uncompr, hello)) 
    {
        cerr << "BAD uncompress!!!\n";
        exit(1);
    } else 
    {
        cout << "uncompress() succeed: \n" << (char *)uncompr;
    }
}

运行结果

orignal size: 51 , compressed size : 22
orignal size: 51 , uncompressed size : 51
uncompress() succeed:
12345678901234567890123456789012345678901234567890 

原创文章 96 获赞 48 访问量 6万+

猜你喜欢

转载自blog.csdn.net/wteruiycbqqvwt/article/details/100118131