如何使用Qt自带的zlib库进行gzip格式的数据压缩与解压缩
从https://github.com/d7185540/QtZlibDemo这里拿到了一个实现, 但是为了测试压缩或解压缩时选用的缓冲区大小是否有影响进行了最简单的修改, 也就是加了个静态变量BufferSize减小缓冲区, 事实证明, 缓冲区哪怕只有40的大小也是可以压缩与解压缩的.
由于之前找到了一个错误的例子, 导致解压缩时总是失败(因为没有正确处理缓冲区过小的问题), 这里找到了正确的例子, 故简化后在此记录.
#include <QtCore/QCoreApplication>
#include <QDebug>
#include <QtZlib/zlib.h>
const int BufferSize = 40;
QByteArray GzipCompress(QByteArray postBody)
{
QByteArray outBuf;
z_stream c_stream;
int err = 0;
int windowBits = 15;
int GZIP_ENCODING = 16;
if (!postBody.isEmpty())
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
c_stream.next_in = (Bytef *)postBody.data();
c_stream.avail_in = postBody.size();
if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) return QByteArray();
for (;;) {
char destBuf[BufferSize] = { 0 };
c_stream.next_out = (Bytef *)destBuf;
c_stream.avail_out = BufferSize;
int err = deflate(&c_stream, Z_FINISH);
outBuf.append(destBuf, BufferSize - c_stream.avail_out);
if (err == Z_STREAM_END || err != Z_OK)
{
break;
}
}
auto total = c_stream.total_out;
deflateEnd(&c_stream);
total = c_stream.total_out;
}
return outBuf;
}
QByteArray GZipUnCompress(QByteArray src)
{
QByteArray outBuffer;
z_stream strm;
strm.zalloc = NULL;
strm.zfree = NULL;
strm.opaque = NULL;
strm.avail_in = src.size();
strm.next_in = (Bytef *)src.data();
int err = -1, ret = -1;
err = inflateInit2(&strm, MAX_WBITS + 16);
if (err == Z_OK) {
while (true)
{
char buffer[BufferSize] = { 0 };
strm.avail_out = BufferSize;
strm.next_out = (Bytef *)buffer;
int code = inflate(&strm, Z_FINISH);
outBuffer.append(buffer, BufferSize - strm.avail_out);
if (Z_STREAM_END == code)
{
break;
}
}
}
inflateEnd(&strm);
return outBuffer;
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QByteArray _src = R"(
#include <QtZlib/zlib.h>
const int BufferSize = 40;
QByteArray GzipCompress(QByteArray postBody)
{
QByteArray outBuf;
z_stream c_stream;
int err = 0;
int windowBits = 15;
int GZIP_ENCODING = 16;
if (!postBody.isEmpty())
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
c_stream.next_in = (Bytef *)postBody.data();
c_stream.avail_in = postBody.size();
if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
MAX_WBITS + GZIP_ENCODING, 8, Z_DEFAULT_STRATEGY) != Z_OK) return QByteArray();
for (;;) {
char destBuf[BufferSize] = { 0 };
c_stream.next_out = (Bytef *)destBuf;
c_stream.avail_out = BufferSize;
int err = deflate(&c_stream, Z_FINISH);
outBuf.append(destBuf, BufferSize - c_stream.avail_out);
if (err == Z_STREAM_END || err != Z_OK)
{
break;
}
}
auto total = c_stream.total_out;
deflateEnd(&c_stream);
total = c_stream.total_out;
}
return outBuf;
}
QByteArray GZipUnCompress(QByteArray src)
{
QByteArray outBuffer;
z_stream strm;
strm.zalloc = NULL;
strm.zfree = NULL;
strm.opaque = NULL;
strm.avail_in = src.size();
strm.next_in = (Bytef *)src.data();
int err = -1, ret = -1;
err = inflateInit2(&strm, MAX_WBITS + 16);
if (err == Z_OK) {
while (true)
{
char buffer[BufferSize] = { 0 };
strm.avail_out = BufferSize;
strm.next_out = (Bytef *)buffer;
int code = inflate(&strm, Z_FINISH);
outBuffer.append(buffer, BufferSize - strm.avail_out);
if (Z_STREAM_END == code)
{
break;
}
}
}
inflateEnd(&strm);
return outBuffer;
}
)";
auto _commpressed = GzipCompress(_src);
auto _uncompressed = GZipUnCompress(_commpressed);
qDebug() << "src size:" << _src.size() << "compressed size:" << _commpressed.size() << "uncompressed size" << _uncompressed.size();
qDebug() << "src.compare(uncompressed) =" << _src.compare(_uncompressed);
return a.exec();
}
本文介绍了如何使用Qt内置的zlib库处理gzip格式的数据压缩和解压缩,通过一个简单的Qt示例,展示了即使缓冲区大小很小也能完成压缩和解压的过程,并纠正了之前解压失败的错误例子。
620





