C++ ZLib GZipStream Decompression NULL terminated -
there lot of questions out there revolving around zlib , gzipstreams none i've found answer question. i'm using c# gzipstream send compressed data client. reads compressed data in entirely tries decompress it. however, each time inflate() called in loop gets null terminated string. when sending binary pretty huge problem.
before show code, wanted if write received compressed bytes .gz file , use gzfile/gzopen/gzread/gzclose works perfectly. means data coming in properly. want read in compressed data, decompress in memory, , have contents in variable.
i think issue inflate() writing char* null terminated. don't know how string. anticipate being major oversight , simple fix. help!
here's decompression code:
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) { { 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>" appended sender signify end of file. removes if (dmsg.find("\n<eof>") != -1) dmsg = dmsg.substr(0, dmsg.find("\n<eof>")); return true; }
working code solution:
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) { // decompressed bytes blockwise using repeated calls inflate { zs.next_out = outbuffer; zs.avail_out = buffersize; ret = inflate(&zs, z_no_flush); if (ret < 0) return false; //here's 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
not problem in itself, can handle binary data. line assumes zero-terminated c-string:
tmpstring << outbuffer;
replace with
tmpstring.append(outbuffer, buffersize);
Comments
Post a Comment