使用zlib压缩IStream流2

来源:互联网 发布:c4.5决策树算法python 编辑:程序博客网 时间:2024/05/22 08:23

使用zlib压缩IStream流2 by sdraogn

这是修改zlib实例的一段代码,用于学习zlib之用。CompressStream()将打开的文件流压缩进IStream流。UncompressStream()反之。注意的是,文件流的读取指针一定要在流的开头,当然也可以在中间,读取中间的数据。其他的问题看看原码再说吧。

#ifndef zipstreamH
#define zipstreamH
//---------------------------------------------------------------------------

#include <windows.h>
#include <objbase.h>        //IStorage, IStream
#include <atl/atlbase.h>    //CComPtr, CComBSTR

namespace zlib{
#include <zlib/zlib.h>
}using namespace zlib;
#pragma link "zlib.lib"

#define Z_BUFFER 8192//8K

#include <cstdio>
#include <cassert>
using namespace std;

int CompressStream(FILE* fin, IStream *stmout, int level = Z_DEFAULT_COMPRESSION);
int UncompressStream(LPSTREAM stmin, FILE *fout);
//---------------------------------------------------------------------------
#endif

源文件:

//---------------------------------------------------------------------------


#pragma hdrstop

#include "zipstream.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)


int CompressStream(FILE* fin, IStream *stmout, int level)
{
    int ret = 0, flush = 0;
    unsigned int nhave = 0;
    z_stream strm   = {0};
    char in[Z_BUFFER]  = {0};
    char out[Z_BUFFER] = {0};

    /* allocate deflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    ret = deflateInit(&strm, level);
    if (ret != Z_OK) return ret;

    /* compress until end of file */
    do
    {
        strm.avail_in = fread(in, 1, Z_BUFFER, fin);
        if (ferror(fin))//on error
        {
            (void) deflateEnd(&strm);
            return Z_ERRNO;
        }
        flush = feof(fin) ? Z_FINISH : Z_NO_FLUSH;
        strm.next_in = in;

        /* run deflate() on input until output buffer not full, finish
           compression if all of source has been read in */
        do
        {
            strm.avail_out = Z_BUFFER;
            strm.next_out = out;
            ret = deflate(&strm, flush);    /* no bad return value */
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
            nhave = Z_BUFFER - strm.avail_out;

            DWORD written = 0;
            stmout->Write(out, nhave, &written);
            if(written!=nhave)
            {
                deflateEnd(&strm);
                return Z_ERRNO;
            }

        } while (strm.avail_out == 0);
        assert(strm.avail_in == 0);     /* all input will be used */

        /* done when last data in file processed */
    } while (flush != Z_FINISH);
    assert(ret == Z_STREAM_END);        /* stream will be complete */

    /* clean up and return */
    (void)deflateEnd(&strm);
    return Z_OK;
}

int UncompressStream(LPSTREAM stmin, FILE *fout)
{
    int ret;
    unsigned have;
    z_stream strm;
    char in[Z_BUFFER];
    char out[Z_BUFFER];

    /* allocate inflate state */
    strm.zalloc = Z_NULL;
    strm.zfree = Z_NULL;
    strm.opaque = Z_NULL;
    strm.avail_in = 0;
    strm.next_in = Z_NULL;
    ret = inflateInit(&strm);
    if (ret != Z_OK)
        return ret;

    /* decompress until deflate stream ends or end of file */
    do
    {
        DWORD dwRead = 0;
        stmin->Read(in, Z_BUFFER, &dwRead);
        strm.avail_in = dwRead;//fread(in, 1, Z_BUFFER, source);
        /*
        if (ferror(source)) {
            (void)inflateEnd(&strm);
            return Z_ERRNO;
        }*/
        if (strm.avail_in == 0)
            break;
        strm.next_in = in;

        /* run inflate() on input until output buffer not full */
        do {
            strm.avail_out = Z_BUFFER;
            strm.next_out = out;
            ret = inflate(&strm, Z_NO_FLUSH);
            assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
            switch(ret)
            {
            case Z_NEED_DICT:
                ret = Z_DATA_ERROR;     /* and fall through */
            case Z_DATA_ERROR:
            case Z_MEM_ERROR:
                (void)inflateEnd(&strm);
                return ret;
            }
            have = Z_BUFFER - strm.avail_out;
            if (fwrite(out, 1, have, fout) != have || ferror(fout))
            {
                (void)inflateEnd(&strm);
                return Z_ERRNO;
            }

            //char buf[32];
            //itoa(strm.avail_in, buf, 10);
            //MessageBox(GetTopWindow(NULL), "", buf, 0);

        } while (strm.avail_out == 0);
        assert(strm.avail_in == 0);     /* all input will be used */
        /* done when inflate() says it's done */
    } while (ret != Z_STREAM_END);

    /* clean up and return */
    (void)inflateEnd(&strm);
    return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}

 
原创粉丝点击