zlib解压缩返回-3(z_data_error)



当我解压缩数据时,zlib解压缩((返回-3(z_data_error(。From-doc:如果输入数据损坏或不完整,则返回Z_DATA_ERROR,

uncompress((Bytef*)uncompressbuffer, &uncompressbuffersize, (const Bytef*)compressbuffer, &compressbuffersize)

在另一个应用程序中,当我使用deflate/inflate时,我会得到同样的错误。

strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = inputLength;
strm.next_in = (unsigned char*) inputBuffer;
ret = inflateInit(&strm);
if (ret != Z_OK)
{
delete[] uncompressedData;
return ERROR;
}
/******************************************************/

strm.avail_out = unusedData; 
strm.next_out = (uncompressedData + MIN_CHUNK) - unusedData;
/* run inflate() on input until output buffer not full */
do {
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);  /* state not clobbered */
switch (ret)
{
case Z_NEED_DICT:
ret = Z_DATA_ERROR;     /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
} while (strm.avail_out != 0 && ret == Z_OK);

但是

此错误仅发生在我的软件的x64版本中。一个工作正常的x86。解压缩后的数据完好无损。压缩和未压缩数据的缓冲区大小正确。Zlib已正确编译为x64。是什么原因导致了这个问题?有什么提示吗?

带有";解压缩":

#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <zlib.h>
#include <assert.h>
#include <cstdlib>
#define CHUNK 16384
const int BUFFERSIZE = 4096;
using namespace std;
void compress(FILE* fin, FILE* fout) {
char buffer[BUFFERSIZE];

int byte_read = fread(buffer, sizeof(char), BUFFERSIZE, fin);

z_stream strm;
int ret;
unsigned have;
unsigned char* tmp = new unsigned char[CHUNK];
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = (unsigned char*)buffer;
strm.avail_in = byte_read;
strm.next_out = tmp;
strm.avail_out = CHUNK;
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
//first loop: compress input data stream and write on RTDB file
do
{
ret = deflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);
have = BUFFERSIZE - strm.avail_out;
fwrite(tmp, sizeof(char), BUFFERSIZE, fout);
} while (strm.avail_out == 0);
//assert(strm.avail_in == 0);
//second loop: all input data consumed. Flush everything...
do
{
strm.next_out = tmp;
strm.avail_out = BUFFERSIZE;
ret = deflate(&strm, Z_FINISH);
assert(ret != Z_STREAM_ERROR);
have = BUFFERSIZE - strm.avail_out;
fwrite(tmp, sizeof(char), BUFFERSIZE, fout);
} while (ret != Z_STREAM_END);
(void)deflateEnd(&strm);
delete tmp;
}
void decompress(FILE* fin, FILE* fout) {
int status;
char buffer[BUFFERSIZE];
int byte_read = fread(buffer, sizeof(char), BUFFERSIZE, fin);
void* compressedBuffer;
void* uncompressedBuffer;
uLongf  compressedBufferSize = BUFFERSIZE;
uLongf  uncompressedBufferSize = BUFFERSIZE;
compressedBuffer = malloc(compressedBufferSize);
uncompressedBuffer = malloc(uncompressedBufferSize);
status = uncompress((Bytef*)uncompressedBuffer, &uncompressedBufferSize, (const Bytef*)buffer, compressedBufferSize);
fwrite(uncompressedBuffer, sizeof(char), BUFFERSIZE, fout);
cout << "Status " << status << endl;
}
int main(int argc, char *argv[]) {

//if (argc == 2)
//{
//  if (strcmp(argv[1], "/?") == 0 || strcmp(argv[1], "--help") == 0)
//  {
//      cout << "Please give me 1 argument" << endl;
//      //getchar();
//      return -1;
//  }
//}
//else
//{
//  cout << "Please give me 1 argument" << endl;
//  //getchar();
//  return -1;
//}
//char *inputdata = argv[1];

//const char *inputdata = "C:\Users\Francesco\source\repos\zlibtest\P0000P0000_no_com-alt.rtdb";
const char *inputdata = "C:\Users\Francesco\source\repos\zlibtest\AAA.txt";
//const char *inputdata = "C:\Users\Francesco\source\repos\zlibtest\P0000P0000_no_com-alt.rtdb";

cout << inputdata << endl;
FILE *fin, *fout, *fdec;
fopen_s(&fin, inputdata, "r+");
fopen_s(&fout, "output.txt", "w+");
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r");
fopen_s(&fdec, "dec.txt", "w");
decompress(fout, fdec);

fclose(fout);
fclose(fdec);
}

您的第一个问题是,当您使用windows时,必须以二进制模式打开压缩文件,否则它将被损坏:

fopen_s(&fout, "output.txt", "w+b");
fopen_s(&fout, "output.txt", "rb");

如果您正在压缩的文件不是文本,或者如果它是文本,并且您希望完全保留它,那么您还应该以二进制模式打开input和dec文件。

接下来在compress中混淆BUFFERSIZECHUNKhave = BUFFERSIZE - strm.avail_out;应该是have = CHUNK - strm.avail_out;,然后需要将have传递给fwrite:fwrite(tmp, sizeof(char), have, fout);

decompress中,您需要将uncompressedBufferSize传递给fwrite,而不是BUFFERSIZE

完全工作的代码(通过一些额外的更改来修复内存泄漏(:

#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <zlib.h>
#include <assert.h>
#include <cstdlib>
#include <array>
const size_t CHUNK_SIZE = 16384;
const size_t BUFFER_SIZE = 4096;
void compress(FILE* fin, FILE* fout) {
std::array<Bytef, BUFFER_SIZE> buffer;
int byte_read = fread(buffer.data(), sizeof(char), buffer.size(), fin);

z_stream strm;
int ret;
unsigned have;
std::vector<Bytef> tmp(CHUNK_SIZE);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.next_in = buffer.data();
strm.avail_in = byte_read;
strm.next_out = tmp.data();
strm.avail_out = tmp.size();
ret = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
//first loop: compress input data stream and write on RTDB file
do
{
ret = deflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR);
have = tmp.size() - strm.avail_out;
fwrite(tmp.data(), sizeof(char), have, fout);
} while (strm.avail_out == 0);
//assert(strm.avail_in == 0);
//second loop: all input data consumed. Flush everything...
do
{
strm.next_out = tmp.data();
strm.avail_out = tmp.size();
ret = deflate(&strm, Z_FINISH);
assert(ret != Z_STREAM_ERROR);
have = tmp.size() - strm.avail_out;
fwrite(tmp.data(), sizeof(char), have, fout);
} while (ret != Z_STREAM_END);
(void)deflateEnd(&strm);
}
void decompress(FILE* fin, FILE* fout) {
int status;
std::array<Bytef, BUFFER_SIZE> compressedBuffer;
std::array<Bytef, BUFFER_SIZE> uncompressedBuffer;
int byte_read = fread(compressedBuffer.data(), sizeof(char), compressedBuffer.size(), fin);
uLongf  compressedBufferSize = compressedBuffer.size();
uLongf  uncompressedBufferSize = uncompressedBuffer.size();
status = uncompress(uncompressedBuffer.data(), &uncompressedBufferSize, compressedBuffer.data(), compressedBufferSize);
fwrite(uncompressedBuffer.data(), sizeof(char), uncompressedBufferSize, fout);
std::cout << "Status " << status << "n";
}
int main(int argc, char* argv[]) {
const char* inputdata = "C:\Users\alan\source\repos\ConanScratch\main.cpp";
std::cout << inputdata << "n";
FILE* fin, * fout, * fdec;
fopen_s(&fin, inputdata, "r+b");
if (!fin)
{
std::cout << "unable to open inputn";
return -1;
}
fopen_s(&fout, "output.txt", "w+b");
if (!fout)
{
std::cout << "unable to open outputn";
return -1;
}
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r+b");
if (!fout)
{
std::cout << "unable to open outputn";
return -1;
}
fopen_s(&fdec, "dec.txt", "wb");
if (!fdec)
{
std::cout << "unable to open decn";
return -1;
}
decompress(fout, fdec);
fclose(fout);
fclose(fdec);
}

使用boost::iostreams:可以极大地简化您的代码

#include <iostream>
#include <fstream>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>
#include <boost/iostreams/filter/zlib.hpp>
int main(int argc, char* argv[])
{
{
std::ifstream input("C:\Users\alan\source\repos\ConanScratch\main.cpp", std::ios_base::binary);
boost::iostreams::filtering_ostream output;
output.push(boost::iostreams::zlib_compressor{});
output.push(boost::iostreams::file_sink("output.txt", std::ios_base::out | std::ios_base::binary));
output << input.rdbuf();
}
{
boost::iostreams::filtering_istream input;
input.push(boost::iostreams::zlib_decompressor{});
input.push(boost::iostreams::file_source("output.txt", std::ios_base::in | std::ios_base::binary));
std::ofstream output("dec.txt", std::ios_base::binary);
output << input.rdbuf();
}
}

最新更新