gpt4 book ai didi

c++ - zlib inflate解压操作

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:25:28 53 4
gpt4 key购买 nike

我有一个包含多个压缩成员的数据缓冲区,它可以是 deflate 或 zlib 压缩成员。

我发现 zlib inflate 调用在处理完第一个压缩 block 后返回 Z_STREAM_END,这里多个压缩成员可以是任意数量(在我的例子中是 3)。但是这些数据来自其他方面,这些方面没有传达有关数据中压缩成员数量的详细信息。

那么我如何实现 zlib inflate 功能的使用,以便它可以在多个压缩成员上工作?

以下是一个示例快速和肮脏的例子,我试图在其中详细说明我的问题。这涉及 zlib 1.2.5 库的情况。

/* example.c -- understanding zlib inflate/decompression operation
*/

#define CHECK_ERR(err, msg) { \
if (err != Z_OK) { \
std::cerr << msg << " error: " << err << std::endl; \
exit(1); \
} \
}

/* ===========================================================================
* deflate() to create compressed data
*/
void test_deflate(std::vector<uint8_t> & input_data, std::vector<uint8_t>& compr)
{
z_stream c_stream; /* compression stream */
int err;

compr.clear();

c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;

err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
CHECK_ERR(err, "deflateInit");

c_stream.next_in = &input_data[0];
c_stream.avail_in = input_data.size();

for (;;) {
uint8_t c_buffer[10] = {};
c_stream.next_out = &c_buffer[0];
c_stream.avail_out = 10;

err = deflate(&c_stream, Z_FINISH);
if (err == Z_STREAM_END)
{
for (int i = 0; i < (10 - c_stream.avail_out); i++)
compr.push_back(c_buffer[i]);
break;
}
CHECK_ERR(err, "deflate");
for (int i = 0; i < (10 - c_stream.avail_out); i++)
compr.push_back(c_buffer[i]);
}

std::cout << "Compressed data (size = " << std::dec << compr.size() << ") = ";
for (int i = 0; i < compr.size(); i++)
std::cout << (uint32_t) compr[i];
std::cout << std::endl;

err = deflateEnd(&c_stream);
CHECK_ERR(err, "deflateEnd");
}

/* ===========================================================================
* Test inflate()
*/
void test_inflate(std::vector<uint8_t> &compr,
std::vector<uint8_t> &uncompr)
{
int err;
z_stream d_stream; /* decompression stream */

uncompr.clear();

d_stream.zalloc = Z_NULL;
d_stream.zfree = Z_NULL;
d_stream.opaque = Z_NULL;
d_stream.avail_in = 0;
d_stream.next_in = Z_NULL;
err = inflateInit(&d_stream);
CHECK_ERR(err, "inflateInit");

d_stream.avail_in = compr.size();
d_stream.next_in = &compr[0];

for(;;) {
uint8_t d_buffer[10] = {};
d_stream.next_out = &d_buffer[0];
d_stream.avail_out = 10;

err = inflate(&d_stream, Z_NO_FLUSH);

if (err == Z_STREAM_END) {
for (int i = 0; i < (10 - d_stream.avail_out); i++)
uncompr.push_back(d_buffer[i]);
if (d_stream.avail_in == 0)
break;
}

CHECK_ERR(err, "inflate");
for (int i = 0; i < (10 - d_stream.avail_out); i++)
uncompr.push_back(d_buffer[i]);
}
err = inflateEnd(&d_stream);
CHECK_ERR(err, "inflateEnd");

std::cout << "Uncompressed data (size = " << std::dec << uncompr.size() << ") = ";
for (int i = 0; i < uncompr.size(); i++)
std::cout << (uint32_t) uncompr[i];
std::cout << std::endl;
}


/* ===========================================================================
* Usage: example
*/

int main(int argc, char **argv)
{
std::vector<uint8_t> input_data;
std::vector<uint8_t> compr, multiple_compr;
std::vector<uint8_t> uncompr;

std::cout << "Input Data (in hex) = ";
for (int i=0; i<32; i++) {
input_data.push_back((uint8_t)i);
if( i && (i % 2 == 0))
std::cout << " ";
std::cout << std::hex << (uint32_t)input_data[i];
}
std::cout << std::endl;

// create compressed buffer-1 from input data
test_deflate(input_data, compr);

// copy compressed buffer-1 data into multiple compressed member buffer
multiple_compr = compr;
compr.clear();

// create compressed buffer-2 from input data
test_deflate(input_data, compr);

// append data of compressed buffer-2 into multiple compressed member buffer
for(int i=0; i< compr.size(); i++)
{
multiple_compr.push_back(compr[i]);
}

// create decompressed output
test_inflate(multiple_compr, uncompr);

// compare decompressed data with input data
std::vector<uint8_t> final_data;
final_data.push_back(input_data);
final_data.push_back(input_data);
if (final_data == uncompr)
std::cout << "Matched" << std::endl;
else
std::cout << "Not Matched" << std::endl;

return 0;
}

1) 这里第二次 inflate 调用返回错误,但我希望它成功进行,为什么它会这样工作?

2) 当我在 inflate 调用参数中使用 Z_FINISH 时它返回错误,为什么我不能在这里使用 Z_FINISH?

请更正我的示例并提出一些优化方法来做同样的事情。

最佳答案

简单地对剩余数据重复膨胀操作。

您可以使用 inflateReset() 代替 inflateEnd()inflateInit() 来节省一些不必要的 free 和 malloc。您可能在 next_inavail_in 中有一些来自上次 inflate 的剩余数据,因此请先使用它,然后重新加载。

关于c++ - zlib inflate解压操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20033014/

53 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com