0

我一直在尝试压缩字符串并将它们保存到文本文件中,然后读取数据并解压缩。但是,当我尝试解压缩读取的字符串时,我得到一个 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 问题。

4

3 回答 3

4

First, you're dealing with binary data that might or might not have embedded null characters. std::string isn't really the correct container for that, although you can handle embedded null characters if you do it correctly. However, using a std::string to store something documents a certain expectation and you're breaking that convention.

Second, the line std::string data(buffer); isn't doing what you think it does - that is the constructor you're supposed to use to construct a string from a null-terminated C string. You're dealing with binary data here so there is a chance that you're either don't get the full buffer into the string because it encounters a null terminator in the middle of the buffer, or it runs off the end of the buffer until it finds a null (or a seg fault). If you absolutely, positively must use a std::string, use the "correct" constructor, which would be std::string data(buffer, length);.

All that said, you are using the wrong data structure - what you want is a dynamic array of char/unsigned char. That would be a std::vector, not a std::string. As an aside, you should also pass the parameters to readFileand writeFile by const reference, the code that you wrote will make copies of the strings and if the buffer you pass into writeFile() is large, that will lead to an unpleasant hit in memory consumption and performance, plus it is completely unnecessary.

于 2013-02-26T14:46:47.120 回答
1

As the file might contain '\0' characters, you should specify the size when you assign the content to the std::string.

std::string data(buffer, length);
于 2013-02-26T14:41:53.917 回答
0

For what it's worth, here's how you could alter readFile() and 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();
}

Then you would also change your compress() and decompress() functions to work with std::vector<char>. Also note that so far the code is lacking any error handling. For example, what happens if the file doesn't exist? After calling file.open() you can check for any error by doing if (!file) { /* error handling */ }.

于 2013-02-27T09:51:50.333 回答