Qt quncompress gzip 数据
我偶然发现一个问题,但找不到解决方案。
所以我想做的是使用 qUncompress(QByteArray) 解压缩 qt 中的数据,以 gzip 格式从 www 发送。我使用wireshark来确定这是有效的gzip流,还使用zip/rar进行了测试,两者都可以解压缩它。
到目前为止的代码如下:
static const char dat[40] = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xaa, 0x2e, 0x2e, 0x49, 0x2c, 0x29,
0x2d, 0xb6, 0x4a, 0x4b, 0xcc, 0x29, 0x4e, 0xad, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00,
0x2a, 0x63, 0x18, 0xc5, 0x0e, 0x00, 0x00, 0x00
};
//this data contains string: {status:false}, in gzip format
QByteArray data;
data.append( dat, sizeof(dat) );
unsigned int size = 14; //expected uncompresed size, reconstruct it BigEndianes
//prepand expected uncompressed size, last 4 byte in dat 0x0e = 14
QByteArray dataPlusSize;
dataPlusSize.append( (unsigned int)((size >> 24) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 16) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 8) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 0) & 0xFF));
QByteArray uncomp = qUncompress( dataPlusSize );
qDebug() << uncomp;
解压缩失败并显示: qUncompress: Z_DATA_ERROR: 输入数据已损坏。
AFAIK gzip 由 10 字节标头、DEFLATE 有效负载、12 字节尾部(8 字节 CRC32 + 4 字节 ISIZE - 未压缩数据大小)组成。 条带化标头和标尾应该让我得到 DEFLATE 数据流,qUncompress 会产生相同的错误。
我检查了 PHP 中压缩的数据字符串,如下所示:
$stringData = gzcompress( "{status:false}", 1);
qUncompress 解压缩该数据。(虽然我没有看到 gzip 标头,即 ID1 = 0x1f, ID2 = 0x8b ) 我用 debug 检查了上面的代码,错误发生在:
if (
#endif
((BITS(8) << 8) + (hold >> 8)) % 31) { //here is error, WHY? long unsigned int hold = 35615
strm->msg = (char *)"incorrect header check";
state->mode = BAD;
break;
}
inflate.c 第 610 行。
我知道 qUncompress 只是 zlib 的包装器,所以我认为它应该毫无问题地处理 gzip。欢迎任何评论。
此致
I stumble upon a problem, and can't find a solution.
So what I want to do is uncompress data in qt, using qUncompress(QByteArray), send from www in gzip format. I used wireshark to determine that this is valid gzip stream, also tested with zip/rar and both can uncompress it.
Code so far, is like this:
static const char dat[40] = {
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xaa, 0x2e, 0x2e, 0x49, 0x2c, 0x29,
0x2d, 0xb6, 0x4a, 0x4b, 0xcc, 0x29, 0x4e, 0xad, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00,
0x2a, 0x63, 0x18, 0xc5, 0x0e, 0x00, 0x00, 0x00
};
//this data contains string: {status:false}, in gzip format
QByteArray data;
data.append( dat, sizeof(dat) );
unsigned int size = 14; //expected uncompresed size, reconstruct it BigEndianes
//prepand expected uncompressed size, last 4 byte in dat 0x0e = 14
QByteArray dataPlusSize;
dataPlusSize.append( (unsigned int)((size >> 24) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 16) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 8) & 0xFF));
dataPlusSize.append( (unsigned int)((size >> 0) & 0xFF));
QByteArray uncomp = qUncompress( dataPlusSize );
qDebug() << uncomp;
And uncompression fails with: qUncompress: Z_DATA_ERROR: Input data is corrupted.
AFAIK gzip consist of 10 byte header, DEFLATE payload, 12 byte trailer ( 8 byte CRC32 + 4 byte ISIZE - uncompresed data size ).
Striping header and trailer should leave me with DEFLATE data stream, qUncompress yields same error.
I checked with data string compressed in PHP, like this:
$stringData = gzcompress( "{status:false}", 1);
and qUncompress uncompress that data.(I didn't see and gzip header though i.e. ID1 = 0x1f, ID2 = 0x8b )
I checked above code with debug, and error occurs at:
if (
#endif
((BITS(8) << 8) + (hold >> 8)) % 31) { //here is error, WHY? long unsigned int hold = 35615
strm->msg = (char *)"incorrect header check";
state->mode = BAD;
break;
}
inflate.c line 610.
I know that qUncompress is simply a wrapper to zlib, so I suppose it should handle gzip without any problem. Any comments are more then welcome.
Best regards
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这是我的贡献...我开发了一个基于
zlib
的类 (QCompressor
),可以使用 GZIP 轻松压缩/解压缩QByteArray
。qcompressor.h
:qcompressor.cpp
:这里是我的测试程序的
main()
:为了让它工作,您需要添加一个将
LIBS += -lz
行添加到您的.pro
文件中,以链接到zlib
。Here is my contribution... I've developed a class (
QCompressor
), based onzlib
for easily compress/decompressQByteArray
using GZIP.qcompressor.h
:qcompressor.cpp
:and here the
main()
of my test program:For let this work, you need to add a line
LIBS += -lz
to your.pro
file for linking againstzlib
.直接使用 zlib 并不难。
我一直这样做:
代码通常是从 zlib 代码示例页面复制的。
您需要
包含
Directly using zlib is not that hard.
I've been doing it like this:
The code is monstly copied from the zlib code example page.
You will need to
include <zlib.h>
您还忘记了
dataPlusSize.append(data);
。但是,这并不能解决你的问题。问题在于,虽然 gzip 和 zlib 具有相同的压缩数据格式,但它们的标头和标尾不同。请参阅:http://www.zlib.net/zlib_faq.html#faq18qUncompress
使用了 zlibuncompress
,因此只能处理 zlib 格式,不能处理 gzip 格式。它需要调用 gzXXXX 函数来处理 gzip 格式。qUncompress
可以处理 PHP 的gzcompress
输出的原因是gzcompress
使用 ZLIB 数据格式压缩给定的字符串。请参阅:http://php.net/manual/en/function.gzcompress.php正如 CiscoIPPhone 提到的,您需要编写自己的函数来处理 gzip 数据。
You also forgot
dataPlusSize.append(data);
. However, that won't solve your problem. The problem is that while gzip and zlib have the same compressed data format, their headers and trailers are different. See: http://www.zlib.net/zlib_faq.html#faq18qUncompress
uses the zlibuncompress
, so it can only handle the zlib format, not the gzip format. It would need to call thegzXXXX
functions to handle the gzip format.The reason that
qUncompress
can handle output from PHP'sgzcompress
is thatgzcompress
compresses the given string using the ZLIB data format. See: http://php.net/manual/en/function.gzcompress.phpAs CiscoIPPhone mentioned, you'll need to write your own to functions to handle gzip data.
灵感来自这个答案和这个答案< /a>,我编写了进一步简化的C++代码。它独立于 Qt。
Inspired from this answer and this answer, I have written further simplified C++ code. It's independent of Qt.