![](/img/trans.png)
[英]zlib gzopen() returns a compressed file stream. Does it decompress the file?
[英]Finding the end of a zlib compressed stream
我正在使用Qt开发NMDC客户端(p2p,DC ++和朋友)。 该协议本身非常简单:
$command parameters|
除了压缩 :
“ ZPipe通过向客户端发送命令$ ZOn |来工作。在$ ZOn之后,将包含一个包含命令的ZLib压缩流。该流将以ZLib定义的EOF结尾。(压缩流中没有$ ZOff!)”
以下是相关代码:
QTcpSocket *conn;
bool compressed;
QByteArray zbuffer;
QByteArray buffer;
// ...
void NMDCConnection::on_conn_readyRead() {
// this gets called whenever we get new data from the hub
if(compressed) { // gets set when we receive $ZOn
zbuffer.append(conn->readAll());
// Magic happens here
if( stream_is_complete ) {
buffer.append(uncompressed_stream);
buffer.append(remainder_of_data);
compressed = false;
}
} else {
buffer.append(conn->readAll());
};
parse(buffer);
}
所以,我怎么得到的值stream_is_complete
, uncompressed_stream
和remainder_of_data
? 我找不到下一个“ $”,因为流可以包含它。 我曾尝试在zlib文档中寻找类似于EOF的内容,但没有这样的东西,实际上,每个流都以看似随机的字符结尾。
我还玩过qUncompress(),但是那需要一个完整的流,仅此而已,仅此而已。
您是否在直接使用zlib?
完全未经测试...
z_stream zstrm;
QByteArray zout;
// when you see a $ZOn|, initialize the z_stream struct
parse() {
...
if (I see a $ZOn|) {
zstrm.next_in = Z_NULL;
zstrm.avail_in = 0;
zstrm.zalloc = Z_NULL;
zstrm.zfree = Z_NULL;
zstrm.opaque = 0;
inflateInit(&zstrm);
compressed = true;
}
}
void NMDCConnection::on_conn_readyRead() {
if (compressed) {
zbuffer.append(conn->readAll());
int rc;
do {
zstrm.next_in = zbuffer.data();
zstrm.avail_in = zbuffer.size();
zout.resize(zstrm.total_out + BLOCK_SIZE);
zstrm.next_out = zout.data() + zstrm.total_out;
zstrm.avail_out = BLOCK_SIZE;
rc = inflate(&zstrm, Z_SYNC_FLUSH);
zbuffer.remove(0, zstrm.next_in - zbuffer.data());
} while (rc == Z_OK && zstrm->avail_out == 0);
if (rc == Z_STREAM_END) {
zout.truncate(zstrm.total_out);
buffer.append(zout);
zout.clear();
buffer.append(zbuffer);
zbuffer.clear();
compress = false;
inflateEnd(&zstrm);
}
else if (rc != Z_OK) {
// ERROR! look at zstrm.msg
}
}
else // whatever
}
此增量解压缩(膨胀)从qbuffer
到qout
,当停止inflate
说:“没有更多的”。
也许最好从QuaZip借用。
文件的结尾对于zlib并不特殊。 我在代码中看到的问题是您使用的是“ readAll()”,实际上它没有任何报告“错误”的方式,例如文件结尾。
您应该尝试在循环中使用“ read()”。 如果您读取了流并且返回了0个字节,则可以确保已到达流的末尾(另一端已关闭连接)。 您已读取的缓冲区,将循环中所有先前“读取”的缓冲区合并在一起,将为您提供完整的缓冲区。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.