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

まず、null 文字が埋め込まれているかどうかに関係なく、バイナリ データを扱っています。std::string正しく行うと、埋め込まれた null 文字を処理できますが、実際にはそのための正しいコンテナーではありません。ただし、 a を使用しstd::stringて何かを保存すると、特定の期待が文書化され、その規則が破られます。

第二に、その行std::string data(buffer);はあなたが思っていることをしていません。これは、null で終わる C 文字列から文字列を構築するために使用することになっているコンストラクターです。ここではバイナリ データを扱っているため、バッファの途中でヌル ターミネータに遭遇したために文字列に完全なバッファを取得できないか、バッファの最後から実行される可能性があります。 null (またはセグフォルト) が見つかるまで。絶対に積極的に std::string を使用する必要がある場合は、「正しい」コンストラクターを使用してstd::string data(buffer, length);ください。

とはいえ、間違ったデータ構造を使用しています。必要なのは、char/unsigned char の動的配列です。それはstd::vectorではなく になりstd::stringます。余談ですが、パラメータを const 参照に渡す必要がありますreadFilewriteFile作成したコードは文字列のコピーを作成し、渡すバッファwriteFile()が大きい場合、メモリ消費とパフォーマンスに不快な打撃を与えます。さらに、それは完全に不要です。

于 2013-02-26T14:46:47.120 に答える
1

ファイルには'\0'文字が含まれている可能性があるため、コンテンツを に割り当てるときにサイズを指定する必要がありますstd::string

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

価値があるのは、変更する方法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 */ }

于 2013-02-27T09:51:50.333 に答える