I'm using a snippet from https://panthema.net/2007/0328-ZLibString.html to compress strings. My problem is that deflateInit() always returns Z_STREAM_ERROR.
According to the zlib manual , that means that the compression level was wrong.
deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough memory, Z_STREAM_ERROR if level is not a valid compression level
The right compression level according to the manual is a value between 0-9.
The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION requests a default compromise between speed and compression (currently equivalent to level 6).
But no matter what value I put for compression, it always returns -2(Z_STREAM_ERROR)
.
#include <string>
#include <stdexcept>
#include <iostream>
#include <iomanip>
#include <sstream>
#include "zlib.h"
std::string compress_string(const std::string& str, int compressionlevel)
{
z_stream zs; // z_stream is zlib's control structure
memset(&zs, 0, sizeof(zs));
//std::cout << deflateInit(&zs, 9); //Always returns -2, no matter if the value is between 0-9
if (deflateInit(&zs, compressionlevel) != Z_OK)
throw(std::runtime_error("deflateInit failed while compressing."));
zs.next_in = (Bytef*)str.data();
zs.avail_in = str.size(); // set the z_stream's input
int ret;
char outbuffer[32768];
std::string outstring;
// retrieve the compressed bytes blockwise
do {
zs.next_out = reinterpret_cast<Bytef*>(outbuffer);
zs.avail_out = sizeof(outbuffer);
ret = deflate(&zs, Z_FINISH);
if (outstring.size() < zs.total_out) {
// append the block to the output string
outstring.append(outbuffer,
zs.total_out - outstring.size());
}
} while (ret == Z_OK);
deflateEnd(&zs);
if (ret != Z_STREAM_END) { // an error occurred that was not EOF
std::ostringstream oss;
oss << "Exception during zlib compression: (" << ret << ") " << zs.msg;
throw(std::runtime_error(oss.str()));
}
return outstring;
}
I'm using zlib 1.2.3 that I got from the Windows GnuWin32 installer. I made a change in zconf.h
and commented out #if 1
and put #if HAVE_UNISTD_H
instead because I'm not on Linux and do not have unistd.h
.
So that looks like
//#if 1 /* HAVE_UNISTD_H -- this line is updated by ./configure */
#if HAVE_UNISTD_H
# include <sys/types.h> /* for off_t */
# include <unistd.h> /* for SEEK_* and off_t */
Extra note: I do not have Z_SOLO
defined.
There are only two ways to get Z_STREAM_ERROR
from deflateInit()
. They are if the first argument is NULL, or if the second argument is not in the range -1..9. By inspection and your claims on the passed compressionLevel, it does not appear that your code could violate either condition.
The only guess I can hazard is that your compile and link of zlib got messed up somewhere, and the types being passed do not match what the routine is expecting, resulting in the routine receiving a different level than what you sent.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.