c++ zlib压缩文件中的字符串

C++ zlib compression of strings in file

本文关键字:字符串 文件 zlib 压缩 c++      更新时间:2023-10-16

我一直在尝试压缩字符串并将它们保存到文本文件中,然后读取数据并解压缩它。然而,当我尝试解压缩所读字符串时,我得到一个Z_BUF_ERROR(-5),字符串可能解压缩也可能不解压缩。

在控制台中,我可以整天压缩/解压:

std::string s = zlib_compress("HELLO asdfasdf asdf asdfasd f asd f asd f awefo@8 892y*(@Y");
std::string e = zlib_decompress(s);

字符串e将毫无困难地返回原始字符串。

但是,当我这样做时:

zlib_decompress(readFile(filename));

我得到一个Z_BUF_ERROR。我想这可能部分是由于文件中隐藏的字符,但我不是很确定。

这是我的readFile函数:

std::string readFile(std::string filename)
{
    std::ifstream file;
    file.open(filename.c_str(), std::ios::binary);
    file.seekg (0, std::ios::end);
    int length = file.tellg();
    file.seekg (0, std::ios::beg);
    char * buffer = new char[length];
    file.read(buffer, length);
    file.close();
    std::string data(buffer);
    return data;
}

当我写压缩数据时,我使用:

void writeFile(std::string filename, std::string data)
{
    std::ofstream file;
    file.open(filename.c_str(), std::ios::binary);
    file << data;
    file.close();
}

如果需要,我将显示用于解压缩的函数,但如果它在没有文件IO的情况下工作,我觉得问题是IO问题。

首先,您要处理的二进制数据可能有也可能没有嵌入空字符。std::string不是真正正确的容器,虽然你可以处理嵌入的空字符,如果你做得正确。然而,使用std::string来存储文档的某些期望,你打破了惯例。

第二,std::string data(buffer);行没有做你认为它做的事情——那是你应该用来从一个以空结尾的C字符串构造一个字符串的构造函数。您在这里处理的是二进制数据,因此有可能无法将整个缓冲区放入字符串中,因为它在缓冲区中间遇到空终止符,或者它在缓冲区的末尾运行,直到找到空(或segfault)。如果绝对必须使用std::string,请使用"正确的"构造函数,即std::string data(buffer, length);

总而言之,你使用了错误的数据结构——你想要的是一个char/unsigned char的动态数组。那将是std::vector,而不是std::string。顺便说一句,您还应该通过const引用将参数传递给readFilewriteFile,您编写的代码将复制字符串,如果您传递给writeFile()的缓冲区很大,这将导致内存消耗和性能方面的不愉快的打击,而且这是完全不必要的。

由于文件可能包含''字符,因此在将内容分配给std::string时应指定其大小。

std::string data(buffer, length);

为了它的价值,这里是如何改变readFile()writeFile():

std::vector<char> readFile(const std::string& filename)
{
    std::ifstream file;
    file.open(filename.c_str(), std::ios::binary);
    file.seekg (0, std::ios::end);
    const int length = file.tellg();
    file.seekg (0, std::ios::beg);
    std::vector<char> data(length);
    file.read(&data[0], length);
    file.close();
    return data;
}
void writeFile(const std::string& filename, const std::vector<char>& data)
{
    std::ofstream file;
    file.open(filename.c_str(), std::ios::binary);
    file.write(&data[0], data.size());
    file.close();
}

然后您还将更改compress()decompress()函数以与std::vector<char>一起工作。还要注意,到目前为止,该代码缺少任何错误处理。例如,如果文件不存在会发生什么?调用file.open()后,您可以通过执行if (!file) { /* error handling */ }来检查任何错误。