gpt4 book ai didi

C++ ZLib GZipStream 解压缩 NULL 终止

转载 作者:行者123 更新时间:2023-11-30 05:32:43 25 4
gpt4 key购买 nike

围绕 zlib 和 GZipStreams 有很多问题,但我发现没有一个可以回答这个问题。我正在使用 C# GZipStream 将压缩数据发送到客户端。它完全读取压缩数据,然后尝试解压缩它。但是,每次在循环中调用 inflate() 时,它只会获得以 NULL 结尾的字符串。发送二进制文件时,这是一个相当大的问题。

在我向您展示代码之前,我只想说,如果我将接收到的压缩字节写入一个 .gz 文件并使用 gzFile/gzopen/gzread/gzclose,一切都会完美无缺。这意味着所有数据都正确输入。我想读入压缩数据,在内存中解压,并将内容保存在一个变量中。

我认为问题在于 inflate() 正在写入以 NULL 终止的 char*。我只是不知道如何让它成为一个字符串。我确实完全预料到这是一个重大疏忽和一个简单的修复。感谢您的帮助!

解压代码如下:

bool DecompressString(const std::string& message, std::string& dMsg)
{
int bufferSize = 512;
int messageSize = message.size() + 1;
//decompress string
z_stream zs;
memset(&zs, 0, sizeof(zs));

zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.next_in = (Bytef*)message.data();
zs.avail_in = messageSize;

int ret = Z_OK;
unsigned char* outbuffer = new unsigned char[bufferSize];

if (inflateInit2(&zs, 16+MAX_WBITS) == Z_OK)
{
do {
zs.next_out = outbuffer;
zs.avail_out = bufferSize;

ret = inflate(&zs, Z_NO_FLUSH);

if (ret < 0) return false;
std::stringstream tmpString;
tmpString << outbuffer;
if (dMsg.size() < zs.total_out) {
dMsg.append(tmpString.str().substr(0, zs.total_out - dMsg.size()));
}
} while (ret == Z_OK);
}

inflateEnd(&zs);
delete[] outbuffer;
//"\n<EOF>" is appended by sender to signify the end of file. This removes it
if (dMsg.find("\n<EOF>") != -1)
dMsg = dMsg.substr(0, dMsg.find("\n<EOF>"));

return true;
}

解决方案的工作代码:

bool DecompressString(const std::string& message, std::string& dMsg)
{
int bufferSize = 512;
int messageSize = message.size() + 1;
//decompress string
z_stream zs;
memset(&zs, 0, sizeof(zs));

zs.zalloc = Z_NULL;
zs.zfree = Z_NULL;
zs.opaque = Z_NULL;
zs.next_in = (Bytef*)message.data();
zs.avail_in = messageSize;

int ret = Z_OK;
unsigned char* outbuffer = new unsigned char[bufferSize];

if (inflateInit2(&zs, 16+MAX_WBITS) == Z_OK)
{
// get the decompressed bytes blockwise using repeated calls to inflate
do {
zs.next_out = outbuffer;
zs.avail_out = bufferSize;

ret = inflate(&zs, Z_NO_FLUSH);

if (ret < 0) return false;
//Here's the difference
if (dMsg.size() < zs.total_out)
dMsg.append(reinterpret_cast<char*>(outbuffer), bufferSize);
//End
} while (ret == Z_OK);
}

inflateEnd(&zs);
delete[] outbuffer;

if (dMsg.find("\n<EOF>") != -1)
dMsg = dMsg.substr(0, dMsg.find("\n<EOF>"));

return true;
}

最佳答案

string 本身没有问题,可以处理二进制数据。正是这一行假定了一个以零结尾的 C 字符串:

tmpString << outbuffer;

替换为

tmpString.append(outbuffer, bufferSize);

关于C++ ZLib GZipStream 解压缩 NULL 终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35043118/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com