C ++ zlib deflate / inflate和stream参数

时间:2012-11-26 17:01:42

标签: c++ compression zlib inflate deflate

在理解了(有一些帮助......)如何使用zlib库的压缩和解压缩功能之后,我现在正试图理解deflate和inflate的工作原理。据我所知,压缩用于一次调用,而deflate可以被调用几次。

使用粒子结构(坐标x,y,z)的简单程序,我可以没有错误地放气我的数据(获得Z_STREAM_END响应),然后用另一个z_stream对象(也是Z_STREAM_END响应)给它们充气。但是当我试图从膨胀响应中显示我的数据时,我可以得到我的结构的x和y坐标而不是第三个(z)。

我认为这是由于我给我的z_stream对象提供了错误的参数,但我无法找到哪一个。据我所知,阅读文档和示例,我认为z_stream的工作原理(这只是一个例子):

// Here i give a total memory size for the output buffer used by deflate func
#define CHUNK 16384

struct Particle
{
    float x;
    float y;
    float z;
};

...

// An element to get a single particule and give it to deflate func
Bytef *dataOriginal = (Bytef*)malloc( sizeof(Particle) );

// This var will be used to pass compressed data
Bytef *dataCompressed = (Bytef*)malloc( CHUNK );

z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, Z_DEFAULT_COMPRESSION);

strm.avail_out = CHUNK;
strm.next_out = dataCompressed;

int nbrLoop = 2;
int spaceUsed = 0;
int flush;
Particle p;

for (var i = 0; i<nbrLoop; i++){
    // set all values equals to 0
    memset( &p, 0, sizeof(Particle) );

    // insert some random values
    p.x = (i+1) * 1;
    p.y = (i+1) * 3;
    p.z = (i+1) * 7;

    //copy this values in a Bytef* elements
    memcpy( dataOriginal, &p, sizeof(Particle) );


    strm.avail_in = sizeof(dataOriginal);
    strm.next_in = dataOriginal;

    // If it's the last particle :
    if(i == nbrLoop - 1){
    flush = Z_FINISH;
    }
    else{
        flush = Z_NO_FLUSH;
    }

    int response = deflate(&strm, flush);

    // I don't get any errors here
    // EDIT : Get Z_OK at first loop, the Z_STREAM_END at second (last)
    if( res == Z_STREAM_END ){
        spaceUsed = CHUNK - strm.avail_out;
    }
}

deflateEnd(&strm);

// Trying to get back my datas
Bytef *decomp = (Bytef*)malloc( sizeof(Particle) );

z_stream strmInflate;
strmInflate.zalloc = Z_NULL;
strmInflate.zfree = Z_NULL;
strmInflate.opaque = Z_NULL;
inflateInit(&strmInflate);

// datas i want to get at the next inflate
strmInflate.avail_in = sizeof(Particle);
strmInflate.next_in = dataCompressed;

// Two particles were compressed, so i need to get back two
strmInflate.avail_out = sizeof(Particle) * 2;
strmInflate.next_out = decomp;

int response = inflate( &strmInflate, Z_NO_FLUSH );
// No error here,
// EDIT : Get Z_OK

inflateEnd( &strmInflate );

Particle testP;
memset( &testP, 0, sizeof(Particle) );
memcpy( &testP, decomp, sizeof(Particle) );

std::cout << testP.x << std::endl; // display 1 OK
std::cout << testP.y << std::endl; // display 3 OK
std::cout << testP.z << std::endl; // display 0 NOT OK

此外,我认为第二次调用膨胀将允许我恢复在我的for循环中创建的第二个粒子的数据,但我无法检索它。

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:2)

strmInflate.avail_in = sizeof(Particle);必须为strmInflate.avail_in = spaceUsed;您必须提供由deflate产生的所有数据。

最后,您希望从Z_STREAM_END获取inflate(),而不是Z_OK。否则,您没有解压缩整个生成的流。

请注意,根据zlib.h中的文档,您还需要在调用之前设置next_inavail_in(如果您愿意,设置为Z_NULL0inflateInit()

根据您将在最终应用程序中使用的输入和输出缓冲区的大小,您可能需要更多循环以确保deflate()inflate()可以完成其工作。请参阅example of how to use zlib