源码:zlib例程 C++

初级代码游戏的专栏介绍与文章目录-CSDN博客

        zlib是zip压缩库,可以实现在程序里使用zip功能(而不用通过执行命令)。

        通过在程序内部使用压缩可以减少写入到磁盘的数据量,虽然用命令行也能实现同样的功能,但是命令行只能用于完整文件,灵活度很低,也不够专业。

        对于超大型数据文件,整个压缩解压缩也不是很合适,耗时耗空间,而程序或许只是需要其中的一小部分数据,如果数据是分块压缩的,则可以只解压少数数据块即可(如果是超大文件,拆分为小文件经常是不可行的)。

        头文件:zlib.h

        链接参数:-lz

        用法相当简单:

ZEXTERN int ZEXPORT compress2 OF((Bytef *dest,   uLongf *destLen,
                                  const Bytef *source, uLong sourceLen,
                                  int level));

ZEXTERN int ZEXPORT uncompress OF((Bytef *dest,   uLongf *destLen,
                                   const Bytef *source, uLong sourceLen));

        就是这一对函数,level是压缩级别,0-9,越大压缩比越高,耗时也越长,默认级别是Z_DEFAULT_COMPRESSION,值是-1。

        参数意思很明显。不过要注意的是,参数是内存区,而不是字符串。对字符串压缩时一定要说明是否包含了字符串结束符。strlen是不包括结束符的。

        由于这是C风格接口,在C++里用包装一下比较好:

//这里还需要一些别的头文件
#include <zlib.h>

	//数据压缩,压缩后数据自带解压缩以后长度
	class CmyZip
	{
	public:
		typedef unsigned long T_LEN;
		//默认压缩级别
		static bool Compress(char const * src, long srclen, CBuffer & output)
		{
			return Compress2(src, srclen, output, Z_DEFAULT_COMPRESSION);
		}
		//level 0-9 越大压缩率越高耗时越长
		static bool Compress2(char const * src, T_LEN srclen, CBuffer & output, int level)
		{
			if (Z_DEFAULT_COMPRESSION == level);
			else if (level < 0)level = 0;
			else if (level > 9)level = 9;
			else;

			if (!output.reserve(compressBound(srclen) + sizeof(T_LEN)))
			{
				cout << "内存不足" << endi;
				return false;
			}
			T_LEN len = output.capacity() - sizeof(T_LEN);
			if (0 != compress2((unsigned char *)output.getbuffer() + sizeof(T_LEN), &len, (unsigned char *)src, srclen, level))
			{
				cout << "压缩失败" << endi;
				return false;
			}
			T_LEN tmp = srclen;
			memmove(output.getbuffer(), &tmp, sizeof(T_LEN));
			output.setSize(sizeof(T_LEN) + len);
			return true;
		}
		static bool UnCompress(char const * src, long srclen, CBuffer & output)
		{
			return _UnCompress(src, srclen, output, 1);
		}
		static bool _UnCompress(char const * src, long srclen, CBuffer & output, long buf_override)
		{
			T_LEN outsize;//压缩数据记录的解压缩后长度
			memmove(&outsize, src, sizeof(T_LEN));
			//cout << "记录的长度 " << outsize << endl;
			if (0 == outsize)
			{
				output.setSize(0);
				return true;
			}
			if (!output.reserve(outsize*buf_override))
			{
				cout << "内存不足" << endl;
				return false;
			}
			unsigned long len = output.capacity();
			int ret = uncompress((unsigned char *)output.getbuffer(), &len, (unsigned char *)src + sizeof(T_LEN), srclen - sizeof(T_LEN));
			if (0 != ret)
			{
				if (Z_MEM_ERROR == ret)
				{
					cout << "解压缩失败 内存不足" << endl;
					return false;
				}
				else if (Z_STREAM_ERROR == ret)
				{
					cout << "解压缩失败 level错误" << endl;
					return false;
				}
				else if (Z_BUF_ERROR)
				{
					cout << "预设缓冲区不足  " << buf_override << " " << output.capacity() << " " << len << endi;
					return _UnCompress(src, srclen, output, buf_override + 1);
				}
				else
				{
					cout << "解压缩失败 " << ret << endl;
					return false;
				}
			}
			if (len != outsize)
			{
				cout << "解压缩后长度与预期不一致 " << len << " " << outsize << endl;
				return false;
			}
			output.setSize(len);
			return true;
		}
	public:
		static int CZip_test(int argc, char ** argv)
		{
			CEasyFile file;
			CBuffer input;
			CBuffer output;
			CBuffer output2;
			if (!file.ReadFile("文件名", input))
			{
				cout << "读文件失败" << endl;
				return __LINE__;
			}
			if (!Compress(input.data(), input.size(), output))return __LINE__;
			cout << input.size() << " " << output.size() << " " << (100 - output.size() * 100 / (input.size() ? input.size() : 1)) << "%" << endl;
			if (!UnCompress(output.data(), output.size(), output2))return __LINE__;
			cout << input.size() << " 解压缩后 " << output2.size() << endl;
			if (!input.Compare(output2))return __LINE__;
			for (long i = 0; i < 10; ++i)
			{
				if (!Compress2(input.data(), input.size(), output, i))return __LINE__;
				cout << i << " " << input.size() << " " << output.size() << " " << (100 - output.size() * 100 / (input.size() ? input.size() : 1)) << "%" << endl;
			}
			return 0;
		}
	};

        自带测试代码CZip_test。

        代码相当简单,应该很容易看懂。用到的CEasyFile和CBuffer在我的其它文章里,功能也都很简单,一目了然。

(这里是结束)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

初级代码游戏

知识究竟是有价还是无价

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值