Compress Data






2.85/5 (24 votes)
Apr 18, 2003

88821

3266
Compress/uncompress data in CFile, CByteArray and IStream(ISequentialStream)
Introduction
This code will compress/decompress data from ISequentialStream
to ISequentialStream
. It also has functions to compress/decompress CFile
and CByteArray
.
Background
While developing software, sometimes I need to compress data to decrease size. The gzip library does compression for me, but it is not ready to handle in-memory or CFile
in MFC. So, here is the class that assists me compressing data.
Using the code
The class Flate
does compression/decompression for ISquentialStream
, CFile
, CByteArray
. Compression for CByteArray
is done by another small utility class 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); };
Here is one function that compresses CFile
data. The internal function uses z_stream
to support custom streams. First, it reads data from input CFile
, compresses it by deflate method and saves it to output 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); }
Here is the other function that uncompresses CFile
data. It is almost same as 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); }