源码:zlib例程 C++

        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 

	//数据压缩,压缩后数据自带解压缩以后长度
	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在我的其它文章里,功能也都很简单,一目了然。

(这里是结束)

你可能感兴趣的:(程序员造轮子(我的可重用代码),c++,开发语言,zlib,zip)