我尝试解压缩用zlib压缩的数据块,并且作者发表评论说,对于解压缩我必须使用inflate_init
和inflate
和Z_SYNC_FLUSH
。我确定这一定必须起作用,因为它以这种方式在php上运行:
$temp = substr($temp, 2, -4);
$temp{0} = chr(ord($temp{0}) | 1);
$temp = gzinflate($temp);
但是我在C ++上解压缩了很多方法,并且每次都失败了。 这是其中之一:
char compressedblockbuffer[3371];
char uncompressedblockbuffer[8192];
is.read(compressedblockbuffer, 3371);
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 3371;
strm.next_in = (Bytef *)compressedblockbuffer;
strm.avail_out = 8192;
strm.next_out = (Bytef *)uncompressedblockbuffer;
inflateInit(&strm);
inflate(&strm, Z_SYNC_FLUSH);
inflateEnd(&strm);
这不是完整的代码,只是显示问题的示例,这就是为什么我指定已知的尺寸。 我使用最后的zlib实现,所以可能是自2003-2004年以来zlib膨胀的变化? 结果是:
所以似乎uncompressedblockbuffer
在2,3,4个索引处包含'\ 0'和许多其他索引,如果我将其打印到控制台,我只看到两个第一个元素。
UPD:
答案 0 :(得分:1)
您要解压缩哪种数据?许多二进制格式完全接受其数据中的NUL字节,因为它只读取为0的值。例如,在许多格式的图像数据内部,它只是在该通道或像素中表示值0(取决于数据大小)。更不用说二进制格式不一定读作字节。 NUL字节实际上可能是2字节或4字节值的一部分。
这是尝试将二进制数据作为字符串读取时的问题。二进制数据不需要遵循文本规则。这就是为什么通常数据边界是一个单独的size
值,因为它不能像文本一样终止在NUL值上。
如果您有原始的未压缩数据进行比较,请将数据加载到内存中并比较数据,或将解压缩的数据保存到文件中,并使用diff工具对文件进行二进制比较。
答案 1 :(得分:1)
如果PHP中的gzinflate()
处理数据,那么您的代码就不会出现。 gzinflate()
期望原始收缩数据。您的代码正在寻找zlib包装的deflate数据。如果要解码原始deflate数据,则需要使用inflateInit2(&strm, -15)
。
您对inflate()
的来电可能会返回您未检查的错误。您需要始终检查zlib例程的返回码,或者任何有可能返回错误的函数。