【发布时间】:2019-05-30 07:54:58
【问题描述】:
我有以下使用 zlib 压缩内存的 C++ 代码 缓冲成 gzip 编码流:
void compress(const std::vector<char>& src)
{
static constexpr int DEFAULT_WINDOW_BITS = 15;
static constexpr int GZIP_WINDOW_BITS = DEFAULT_WINDOW_BITS + 16;
static constexpr int GZIP_MEM_LEVEL = 8;
z_stream stream;
const auto srcData = reinterpret_cast<unsigned char*>(const_cast<char*>(src.data()));
stream.zalloc = Z_NULL;
stream.zfree = Z_NULL;
stream.opaque = Z_NULL;
stream.next_in = srcData;
stream.avail_in = src.size();
auto result = deflateInit2(&stream,
Z_DEFAULT_COMPRESSION,
Z_DEFLATED,
GZIP_WINDOW_BITS,
GZIP_MEM_LEVEL,
Z_DEFAULT_STRATEGY);
if (result == Z_OK)
{
std::vector<char> dest(deflateBound(&stream, stream.avail_in));
const auto destData = reinterpret_cast<unsigned char*>(dest.data());
stream.next_out = destData;
stream.avail_out = dest.size();
result = deflate(&stream, Z_FINISH);
if (result == Z_STREAM_END)
{
std::cout << "Original: " << src.size() << "; compressed: " << dest.size() << std::endl;
}
else
{
std::cerr << "Error when compressing: code " << std::to_string(result);
}
result = deflateEnd(&stream);
if (result != Z_OK)
{
std::cerr << "Error: Cannot destroy deflate stream: code " << std::to_string(result) << std::endl;
}
}
else
{
std::cerr << "Error: Cannot initialize deflate stream: code " << std::to_string(result) << std::endl;
}
}
虽然函数成功完成,但我没有得到压缩 一点也不。实际上,对于仅包含字符“a”的 3MB 文件 重复多次,我得到以下信息:
Original: 3205841; compressed: 3206843
我是不是做错了什么?
(请注意,这是原始代码的简化版本;实际上,我会使用 RAII 和异常来处理资源和错误)。
【问题讨论】:
-
你为什么用
dest.size()而不是stream.total_out? -
哦,该死的......你是对的,这确实显示了更小的尺寸。但是,为什么 deflateBound 一开始就给出这么大的数字呢?
-
"deflateBound() 和 compressBound() 函数可用于提供扩展的上限,以允许分配确保足够大以容纳整个压缩输出的输出缓冲区。” - 上限 = 最坏情况
-
如果您想查看最坏的情况,请使用随机或加密数据作为输入