65.9K
CodeProject 正在变化。 阅读更多。
Home

压缩数据

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.85/5 (24投票s)

2003 年 4 月 18 日

viewsIcon

89438

downloadIcon

3266

在 CFile、CByteArray 和 IStream(ISequentialStream) 中压缩/解压缩数据

引言

这段代码将从 ISequentialStream 压缩/解压缩数据到 ISequentialStream。它还具有压缩/解压缩 CFileCByteArray 的函数。

背景

在开发软件时,有时我需要压缩数据以减小其大小。gzip 库为我执行压缩,但它无法处理 MFC 中的内存或 CFile。因此,这里有一个辅助我压缩数据的类。

使用代码

FlateISquentialStreamCFileCByteArray 进行压缩/解压缩。对 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);
}
© . All rights reserved.