C ++ ZLib GZipStream Декомпрессия NULL прекращена

Есть много вопросов, связанных с zlib и GZipStreams, но ни один из тех, что я нашел, не отвечает на этот вопрос. Я использую C # GZipStream для отправки сжатых данных клиенту. Он полностью читает сжатые данные, а затем пытается распаковать их. Однако каждый раз, когда inflate () вызывается в цикле, он получает только завершенную строку NULL. При отправке двоичного файла это довольно большая проблема.

Прежде чем я покажу вам код, я просто хотел сказать, что если я записываю полученные сжатые байты в файл .gz и использую gzFile / gzopen / gzread / gzclose, все работает отлично. Это означает, что все данные поступают правильно. Я хочу читать сжатые данные, распаковывать их в памяти и хранить содержимое в переменной.

Я думаю, что проблема в том, что inflate () записывает в char *, который завершается NULL. Я просто не знаю, как заставить это быть последовательностью. Я полностью ожидаю, что это будет серьезным упущением и простым исправлением. Спасибо за любую помощь!

Вот код распаковки:

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;
}

1

Решение

string сама по себе не является проблемой, она может обрабатывать двоичные данные.
Именно эта строка предполагает завершающуюся нулем c-строку:

tmpString << outbuffer;

Замени это

tmpString.append(outbuffer, bufferSize);
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]