zlib解压return-3(z_data_error)
zlib decompression return -3 (z_data_error)
zlib uncompress() return -3 (z_data_error) 当我解压缩数据时。
来自文档:returns 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。
还有什么可能导致这个问题?有什么提示吗?
带有“uncompress”的示例代码:
#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");
如果您正在压缩的文件不是文本,或者如果它是文本并且您想完美地保存它,您还应该以二进制模式打开输入和 dec 文件。
接下来在compress
中你把BUFFERSIZE
和CHUNK
搞混了,have = 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 input\n";
return -1;
}
fopen_s(&fout, "output.txt", "w+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
fopen_s(&fdec, "dec.txt", "wb");
if (!fdec)
{
std::cout << "unable to open dec\n";
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();
}
}
zlib uncompress() return -3 (z_data_error) 当我解压缩数据时。 来自文档:returns 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。 还有什么可能导致这个问题?有什么提示吗?
带有“uncompress”的示例代码:
#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");
如果您正在压缩的文件不是文本,或者如果它是文本并且您想完美地保存它,您还应该以二进制模式打开输入和 dec 文件。
接下来在compress
中你把BUFFERSIZE
和CHUNK
搞混了,have = 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 input\n";
return -1;
}
fopen_s(&fout, "output.txt", "w+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
compress(fin, fout);
fclose(fin);
fclose(fout);
fopen_s(&fout, "output.txt", "r+b");
if (!fout)
{
std::cout << "unable to open output\n";
return -1;
}
fopen_s(&fdec, "dec.txt", "wb");
if (!fdec)
{
std::cout << "unable to open dec\n";
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();
}
}