在压缩文本时,我希望维护地球上其他应用程序(包括web应用程序)之间的互操作性。由于qCompress和qUncompress似乎背道而驰,所以我尝试直接从Qt应用程序中使用zlib。
我将接受最简单(最简单)的答案,它向我展示了如何使用带有QByteArray的或的zlib库,修改qCompress的输出,以便它可以在Qt应用程序之外使用。
下面是我尴尬的尝试:
QByteArray tdata = QString("Oh noes!").toUtf8();
QByteArray cdata;
uLongf len = 12 + 1.002*tdata.length();
compress(&cdata, &len, &tdata, tdata.length());而错误是:
错误:不能将参数'1‘的'QByteArray*’转换为'Bytef*‘到'int compress’( Bytef*,uLongf*,const *,uLong)‘
然后,我尝试使用QByteArray::constData()
compress(cdata.constData(), &len, &tdata, tdata.length());但是得到了以下错误:
错误:从“const char*”到“Bytef*”的转换无效
我不知道Bytef是什么,所以我开始在zlib源代码中进行调查。但我所能找到的只有QtSources/src/3 3rdparty/zlib/zconf.h.h
# define Bytef z_Bytef所以现在我迷路了。
发布于 2012-01-10 22:12:21
根据这在qUncompress中的注释,我认为这很容易。
注意:如果您想使用这个函数来解压缩使用zlib压缩的外部数据,那么首先需要在包含数据的字节数组中添加一个4字节的头。报头必须包含未压缩数据的预期长度(以字节为单位),表示为无符号、大端、32位整数。
所以你可以像这样压缩它:
QByteArray tdata = QString("Oh noes!").toUtf8();
QByteArray compressedData = qCompress(tdata);
compressedData.remove(0, 4);发布于 2012-01-10 21:49:34
下面是我曾经编写的一些代码,这些代码作为输入获取指向字节数组的指针、要压缩的字节数和压缩级别,然后使用zlib压缩输入。结果以字符串形式返回。
enum compressionLevel
{
clFast,
clSmall,
clDefault
};
const size_t ChunkSize = 262144; //256k default size for chunks fed to zlib
void compressZlib(const char *s, size_t nbytes, std::string &out, compressionLevel l /*= clDefault*/ )
{
int level = Z_DEFAULT_COMPRESSION;
switch (l)
{
case clDefault:
level = Z_DEFAULT_COMPRESSION; break;
case clSmall:
level = Z_BEST_COMPRESSION; break;
case clFast:
level = Z_BEST_SPEED; break;
};
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
int ret = deflateInit(&strm, level);
if (ret != Z_OK)
{
throw std::runtime_error("Error while initializing zlib, error code "+ret);
}
size_t toCompress = nbytes;
char *readp = (char*)s;
size_t writeOffset = out.size();
out.reserve((size_t)(nbytes * 0.7));
while (toCompress > 0)
{
size_t toRead = std::min(toCompress,ChunkSize);
int flush = toRead < toCompress ? Z_NO_FLUSH : Z_FINISH;
strm.avail_in = toRead;
strm.next_in = (Bytef*)readp;
char *writep = new char[ChunkSize];
do{
strm.avail_out = ChunkSize;
strm.next_out = (Bytef*)writep;
deflate(&strm, flush);
size_t written = ChunkSize - strm.avail_out;
out.resize(out.size() + written);
memcpy(&(out[writeOffset]), writep, written);
writeOffset += written;
} while (strm.avail_out == 0);
delete[] writep;
readp += toRead;
toCompress -= toRead;
}
(void)deflateEnd(&strm);
}也许这可以帮助您解决问题,我想使用cdata.constData()可以直接调用这个函数
发布于 2012-01-10 22:20:17
只是为了帮你解决问题的最后一部分:
我不知道Bytef是什么,所以我开始在zlib源代码中进行调查。
有关Byte和Bytef的定义,请参阅zconf.h .h的第332和333行以及第342行:
332 #if !defined(__MACTYPES__)
333 typedef unsigned char Byte; /* 8 bits */
...
338 #ifdef SMALL_MEDIUM
339 /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */
340 # define Bytef Byte FAR
341 #else
342 typedef Byte FAR Bytef; FAR的定义是用于混合模式的MSDOS编程,否则它不会被定义为任何东西(参见zcon.h第328-330行)。
因此,zlib类型的Bytef和Byte与大多数平台上的unsigned char基本相同。因此,您应该能够-执行以下操作:
QByteArray tdata = QString("Oh noes!").toUtf8();
QByteArray cdata(compressBound(tdata.length()), '\0');
uLongf len = compressBound(tdata.length());
compress(reinterpret_cast<unsigned char*>(cdata.data()), &len,
reinterpret_cast<unsigned char*>(tdata.data()), tdata.length());https://stackoverflow.com/questions/8810897
复制相似问题