zlib - gzip 的零压缩率
zlib - Zero compression rate for gzip
我有以下C++代码,它使用 zlib 压缩内存 缓冲区到 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()
没有,也无法通过deflate()
更改。您从dest.size()
得到的只是压缩前输出缓冲区的大小。您需要查看从deflate()
调用返回的内容,以确定压缩结果的大小。这可以是dest.size() - strm.avail_out
,也可以是strm.total_out
。
在单个调用中进行压缩意味着您需要将输入和输出缓冲区大小都拟合在一个unsigned
中,通常为 32 位。因此,您只能压缩大约 4 GB 的数据。如果你可能需要做更多的事情,那么你需要一个循环,为较小的块调用deflate()
。可能更小的块,以 10 或 100 KB 为单位。这是通常的使用方式deflate()
,因为它占用的内存要少得多,并且可以防止您的例程在这方面成为资源消耗者。
deflateBound()
专门用于支持使用单个deflate()
调用。它提供了可能的压缩大小的上限,该上限可能比输入数据大一点。当输入数据不可压缩时,例如已经压缩或随机时,就是这种情况。
相关文章:
- C++中高效的大型稀疏块压缩线性方程
- 嵌入方指针压缩已禁用
- 带有 GZIP 压缩的原型
- 使用 libarchive 将 gzip 文件解压缩到内存
- zlib - gzip 的零压缩率
- 压缩算法(例如gzip、zip或snappy)的输出肯定小于输入吗
- 使用 curl 解压缩 gzip 数据
- 使用 qCompress 使用 GZip 压缩字符串
- Gzip 压缩/解压缩长字符数组
- zlib compress() 产生了可怕的压缩率
- C++/zlib/gzip压缩和C#GZipStream解压缩失败
- 可以提高iostream读取和压缩gzip文件的速度
- 提升 gzip 解压缩字节数组
- 将boost gzip压缩器封装在易于使用的函数/类中
- C -我如何gzip解压缩块文件到内存缓冲区
- 如何使用miniz创建一个可以通过gzip解压的压缩文件
- c++ boost gzip内存二进制压缩
- Windows 8 (Store App) in C -如何禁用gzip压缩
- 使用gzip写入gzip压缩文件
- 如何检查文件是否被 gzip 压缩