压缩数据






2.85/5 (24投票s)
2003 年 4 月 18 日

89438

3266
在 CFile、CByteArray 和 IStream(ISequentialStream) 中压缩/解压缩数据
引言
这段代码将从 ISequentialStream
压缩/解压缩数据到 ISequentialStream
。它还具有压缩/解压缩 CFile
和 CByteArray
的函数。
背景
在开发软件时,有时我需要压缩数据以减小其大小。gzip 库为我执行压缩,但它无法处理 MFC 中的内存或 CFile
。因此,这里有一个辅助我压缩数据的类。
使用代码
类 Flate
对 ISquentialStream
、CFile
、CByteArray
进行压缩/解压缩。对 CByteArray
的压缩是通过另一个小型实用程序类 CBAStreamReader
/CBAStreamWriter
完成的。
// // class Flate declaration. // class Flate { public: Flate() { } void Inflate(ISequentialStream* pOutput, ISequentialStream* pInput); void Deflate(ISequentialStream* pOutput, ISequentialStream* pInput); void Inflate(CFile* pOutput, CFile* pInput); void Deflate(CFile* pOutput, CFile* pInput); BOOL Compress(CByteArray& dst, const CByteArray& src) { return Compress(dst, src.GetData(), src.GetSize()); } BOOL Compress(CByteArray& dst, const BYTE* src, UINT srcLen); BOOL Uncompress(CByteArray& dst, const CByteArray& src) { return Uncompress(dst, src.GetData(), src.GetSize()); } BOOL Uncompress(CByteArray& dst, const BYTE* src, UINT srcLen); };
这里有一个压缩 CFile
数据的函数。内部函数使用 z_stream
来支持自定义流。首先,它从输入 CFile
读取数据,通过 deflate 方法压缩它,并将其保存到输出 CFile
。
// // Deflate method compresses CFile based data. // void Flate::Deflate(CFile* pOutput, CFile* pInput) { z_stream zstm; memset(&zstm,0,sizeof(z_stream)); BYTE zBufIn[UNCOMP_BUFSIZE]; BYTE zBufOut[COMP_BUFSIZE]; deflateInit(&zstm, Z_DEFAULT_COMPRESSION); int err = Z_OK; while ( TRUE ) { UINT cbRead = 0; cbRead = pInput->Read(zBufIn, sizeof(zBufIn)); if ( cbRead == 0 ) break; zstm.next_in = (Bytef*)zBufIn; zstm.avail_in = (uInt)cbRead; while ( TRUE ) { zstm.next_out = (Bytef*)zBufOut; zstm.avail_out = sizeof(zBufOut); err = deflate(&zstm, Z_SYNC_FLUSH); if (err != Z_OK) break; UINT cbWrite = sizeof(zBufOut) - zstm.avail_out; if ( cbWrite == 0 ) break; pOutput->Write(zBufOut, cbWrite); if ( zstm.avail_out != 0 ) break; } } err = deflateEnd(&zstm); }
这是另一个解压缩 CFile
数据的函数。它几乎与 Inflate
相同。
// // Inflate methods uncompresses CFile based data. // void Flate::Inflate(CFile* pOutput, CFile* pInput) { z_stream zstm; memset(&zstm,0,sizeof(z_stream)); BYTE zBufIn[COMP_BUFSIZE]; BYTE zBufOut[UNCOMP_BUFSIZE]; inflateInit(&zstm); int err = Z_OK; while ( TRUE ) { UINT cbRead = 0; cbRead = pInput->Read(zBufIn, sizeof(zBufIn)); if ( cbRead == 0 ) break; zstm.next_in = (Bytef*)zBufIn; zstm.avail_in = (uInt)cbRead; while ( TRUE ) { zstm.next_out = (Bytef*)zBufOut; zstm.avail_out = sizeof(zBufOut); err = inflate(&zstm, Z_SYNC_FLUSH); if (err != Z_OK) break; UINT cbWrite = sizeof(zBufOut) - zstm.avail_out; if ( cbWrite == 0 ) break; pOutput->Write(zBufOut, cbWrite); if ( zstm.avail_out != 0 ) break; } } err = inflateEnd(&zstm); }