zlib实现流式解压

#define CHUNK_SIZE 4096
class CZipFileStream {

	// zlib支持.
	z_stream m_stream;
	int m_last_inflate_;
	// 解压缓冲.
	char m_zlib_buffer[CHUNK_SIZE];
	// 输入的字节数.
	std::size_t m_zlib_buffer_size;
	std::ifstream& m_fs;
	bool m_auto_close_fs;
public:
	/// <summary>
	/// 构造一个解压类
	/// </summary>
	/// <param name="fs">输入的文件流</param>
	/// <param name="autoClosefs">是否自动关闭文件,默认不自动关闭</param>
	CZipFileStream(std::ifstream& fs,bool autoClosefs=false) :m_fs(fs), m_auto_close_fs(autoClosefs), m_last_inflate_(Z_OK)
	{
		memset(&m_stream, 0, sizeof(z_stream));
		//inflateInit(&m_stream);
	}
	~CZipFileStream()
	{
		if (m_stream.zalloc)
			inflateEnd(&m_stream);
		if (m_auto_close_fs && m_fs.is_open())
			m_fs.close();
	}

	int Read(BYTE* buf, std::size_t bufsize)
	{
		if (!m_fs.is_open())
		{
			m_last_inflate_ = Z_DATA_ERROR;
			return 0;
		}
		if (IsBadReadPtr(buf, bufsize) || buf == 0)
		{
			m_last_inflate_ = Z_BUF_ERROR;
			return 0;
		}
		if (!m_stream.zalloc)
		{
			m_last_inflate_ = inflateInit(&m_stream);
			if (m_last_inflate_ != Z_OK)
			{
				return m_last_inflate_;
			}
		}
		m_stream.next_out = (Bytef*)buf;
 		m_stream.avail_out = bufsize;
		while (!m_fs.eof()|| m_stream.avail_in)
		{
			if (m_stream.avail_in == 0)
			{
				m_fs.read(m_zlib_buffer, CHUNK_SIZE);
				m_zlib_buffer_size = m_fs.gcount();
				m_stream.avail_in = (uInt)m_zlib_buffer_size;
				m_stream.next_in = (z_const Bytef*) & m_zlib_buffer[0];
			}
			//没有数据读出来。
			if (m_zlib_buffer_size == 0)
			{
				if (m_stream.zalloc)
				{
					inflateEnd(&m_stream); 
					m_last_inflate_ = Z_STREAM_END;
				}
				break;
			}
			m_last_inflate_ = inflate(&m_stream, Z_SYNC_FLUSH);
			//解压完了就不管输出是否满了
			if (m_last_inflate_ == Z_STREAM_END)
			{
				if (m_auto_close_fs)
					m_fs.close();
				if (m_stream.zalloc)
					inflateEnd(&m_stream);
				return bufsize-m_stream.avail_out;
			}
			//如果解压成功又没有填满输出则继续读数据
			else if (m_last_inflate_ == Z_OK)
			{
				if (m_stream.avail_out)
					continue;
				else 
					return bufsize-m_stream.avail_out;
			}
			else
			{//到这说明出错了
				if (m_stream.zalloc)
				{
					if (m_auto_close_fs)
						m_fs.close();
					inflateEnd(&m_stream);
				}
				break;
			}
		}
		return 0;
	}
    //判断文件是否解压完成
	bool Eof()
	{
		return (m_last_inflate_ == Z_STREAM_END || m_last_inflate_!=Z_OK);
	}
    //正常情况下解压完成了都应该是Z_STREAM_END ,此函数可以判断解压的数据最后是否成功
	bool IsOk()
	{
		return (m_last_inflate_ == Z_STREAM_END );
	}
	//直接解压所有的数据,需要提前知道需要的缓冲大小。
	static bool UnCompress(const BYTE* pcCompBuf, uLong ulCompLen, BYTE* pcUnCompBuf, uLong& uncomprLen)
	{
		if (pcCompBuf == NULL)
		{
			return false;
		}
		int err = uncompress(pcUnCompBuf, &uncomprLen, (const Bytef*)pcCompBuf, ulCompLen);
		if (err != Z_OK)
		{
			return false;
		}
		return true;
	}
};

调用大概如下。代码初步测试通过。静态函数UnCompress是一次解压所有数据。可以用它验证解压数据,但是它的缓冲区需要留得足够大。

std::ifstream infile(inputPath.c_str(), std::ios_base::binary | std::ios_base::in);

CZipFileStream zipstreame(infile,true);
		std::vector<BYTE> outbuf;

		while (!zipstreame.Eof())
		{
			BYTE buf[1024];
			int readcount = zipstreame.Read(buf, sizeof(buf));
			outbuf.insert(outbuf.end(), buf, buf + readcount);			
		}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值