Ale*_*lds 0 c c++ compression zlib
我试图用一些使用zlib1.2.8的代码调试问题.问题是这个较大的项目可以创建存档,但Z_DATA_ERROR在尝试提取该存档时会遇到标题问题.
为此,我用C++编写了一个小型测试程序,压缩("缩小")指定的常规文件,将压缩数据写入第二个常规文件,并提取("膨胀")到第三个常规文件,一行为一时间 我然后diff第一个和第三个文件,以确保我得到相同的字节.
作为参考,该测试项目位于:https://github.com/alexpreynolds/zlib-test并在Clang下编译(也应该在GNU GCC下编译).
我更大的问题是如何在我的大项目中正确处理标题数据.
在我的第一个测试场景中,我可以使用以下代码设置压缩机械:
z_error = deflateInit(this->z_stream_ptr, ZLIB_TEST_COMPRESSION_LEVEL);
Run Code Online (Sandbox Code Playgroud)
在这里,ZLIB_TEST_COMPRESSION_LEVEL是1为了提供最佳速度.然后我deflate()在z_stream指针上运行,直到没有任何东西从压缩中消失.
要提取这些字节,我可以使用inflateInit():
int ret = inflateInit(this->z_stream_ptr);
Run Code Online (Sandbox Code Playgroud)
那么在这种情况下标题格式是什么?
在我的第二个测试场景中,我设置了deflate机器,如下所示:
z_error = deflateInit2(this->z_stream_ptr,
ZLIB_TEST_COMPRESSION_LEVEL,
ZLIB_TEST_COMPRESSION_METHOD,
ZLIB_TEST_COMPRESSION_WINDOW_BITS,
ZLIB_TEST_COMPRESSION_MEM_LEVEL,
ZLIB_TEST_COMPRESSION_STRATEGY);
Run Code Online (Sandbox Code Playgroud)
这些放气常数分别是,1对于电平,Z_DEFLATED为方法,15+16或31对窗口位,8用于存储器级,并Z_DEFAULT_STRATEGY为策略.
前inflateInit()呼叫不起作用; 相反,我必须使用inflateInit2()并指定一个修改的窗口位值:
int ret = inflateInit2(this->z_stream_ptr, ZLIB_TEST_COMPRESSION_WINDOW_BITS + 16);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,窗口位值不是31在deflateInit2()调用中,而是15+32或47.
如果我使用31(或任何其他值47),那么我Z_DATA_ERROR接下来的inflate()电话.也就是说,如果我使用相同的窗口位进行inflateInit2()调用:
int ret = inflateInit2(this->z_stream_ptr, ZLIB_TEST_COMPRESSION_WINDOW_BITS);
Run Code Online (Sandbox Code Playgroud)
然后我尝试以下错误时收到以下错误inflate():
Error: inflate to stream failed [-3]
Run Code Online (Sandbox Code Playgroud)
在这里,-3是一样的Z_DATA_ERROR.
根据文档,使用31with deflateInit2()应该写一个gzip标题和预告片.因此,31在下面的inflateInit2()调用应该期望能够提取头信息.
为什么修改后的值47有效,但不是31?
我的测试项目大致类似于zlib网站上的示例代码,但提取/通胀代码除外,它一次膨胀一个z_stream块并解析输出的换行符.
inflate()只有当提出一个新的提取数据缓冲区时才会运行一些特殊的东西- 比如在inflate()调用之间缺少标题信息- 而不是像在zlib示例代码中一样运行整个提取?
我更大的调试问题是寻找一种zlib仅在请求时提取一块压缩数据的强大方法,这样我就可以一次提取一行数据,而不是获取整个提取文件.关于我处理zlib格式参数的方式似乎搞砸了我,但我无法弄清楚为什么或如何解决这个问题.
deflateInit()和inflateInit(),以及deflateInit2()和inflateInit2()与windowBits在0..15所有过程的zlib包裹DEFLATE数据.(参见RFC 1950和RFC 1951.)
deflateInit2()并且在-1 ..- 15中处于inflateInit2()负数windowBits,处理原始收缩数据,没有标题或预告片. deflateInit2()和inflateInit2()与windowBits在16..31,即16加入到0..15,过程gzip的包裹的放气数据(RFC 1952). inflateInit2()与windowBits在32..47(32加入到0..15)将自动检测或者一个gzip或zlib的报头(但不是原始DEFLATE数据),并且相应地解压缩.
为什么修改后的值47有效,但不是31?
31确实有效.我没有尝试查看你的代码来调试它.
只有当提出一个新的提取数据缓冲区时才会运行inflate()有什么特别之处 - 比如在inflate()调用之间缺少头信息 - 而不是像在zlib示例代码中那样在一次传递中运行整个提取?
我无法弄清楚你在这里问的是什么.也许一个更明确的例子会有所帮助.整点inflate()是一次解压缩一块.