0

作業中の製品の 1 つに、次の構造を持つファイルが含まれています。

A STRING WITH SOME CONTENT IDENTIFYING THE FILES CONTENTS
A STRING ON ROW 2
A STRING ON ROW 3
A STRING ON ROW 4
<binary data starts here and is gzipped>

これを行うと、コンテンツを解凍し、同じファイルの圧縮されていないバージョンを再作成できます。

INPUT=FILEA.COMPRESSED
OUTPUT=FILEB.UNCOMPRESSED
head -n5 $INPUT > $OUTPUT
cat $INPUT | tail --lines=+5 | gunzip >> $OUTPUT

# At this point I'm left with a file structure as follows:
A STRING WITH SOME CONTENT IDENTIFYING THE FILES CONTENTS
A STRING ON ROW 2
A STRING ON ROW 3
A STRING ON ROW 4
<uncompressed content>

私はこれと同じ偉業をブーストで達成しようとしています。Boost は常にgzip.hpp がbad_headerとして明らかにするgzip_errorコード4をスローします

私が作業しているファイルは間違いなく防弾ではなく、非常に古いレガシー システムによって生成されています。

私の主な質問: gunzip がそれを実行できる場合...ブーストで見落としている微調整またはフラグはありますか?

失敗している C++ コードは次のようになります (ポイントに焦点を当てるために大幅に簡略化されているため、構文エラーが含まれている可能性があります)。

#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <sstream>
#include <iostream>
#include <fstream>

// Open File
ifstream file("myfile", ios::in|ios::binary);

int line = 1;
char c;
while (!file.eof() && line < 5){
   // I do do 'way' more error checking and proper handling here
   // in real code, but you get the point.. I'm moving the cursor
   // past the last new line and the beginning of what is otherwise
   // compressed content.
   file.get(c);
   if(c == '\n')line++;
}

stringstream ss;
// Store rest of binary data into stringstream
while(!file.eof()){
   file.get(c);
   ss.put(c);
}
// Close File
file.close();

// Return file pointer to potential gzip stream
ss.seekg(0, ios::beg);
try
{
   stringstream gzipped(ss.str());
   io::filtering_istream gunzip;
   gunzip.push(io::gzip_decompressor());
   gunzip.push(gzipped);
   copy(gunzip, ss);
}
catch(io::gzip_error const&  ex)
   // always throws error code 4 here (bad_header)
   cout << "Exception: " << ex.error() << endl;

以下に、さらに役立つ情報を示します。

  • OS:レッドハット 5.7
  • ブースト: boost-1.33.1-10 (el5 リポジトリ)
  • プラットフォーム: x86_64
  • GCC:バージョン 4.1.2 20080704 (Red Hat 4.1.2-46)

私の Makefile には、リンカーにも次の行があります。

LDFLAGS = -lz -lboost_iostreams
4

1 に答える 1

0

それがエラーの根本原因であるかどうかはわかりませんが、の使用file.eof()は正しくありません。この関数は、ファイルの末尾を超えて読み取りを試みた後にのみ true を返します。次の読み取りが失敗したかどうかは通知されません。

while(!file.eof()){ //1
   file.get(c);  // 2
   ss.put(c);    // 3
}

このループでは、2 行目の最後の有効な文字を読み取ると、3 行目に出力します。次に、1 行目の条件を再度テストします。ファイルの末尾を超えて読み取ろうとしていないfile.eof()ため、false が返され、ループ条件が true になります。次に、次の文字を読み取ろうとしますが失敗し、c変更されません。次に、3 行目でその無効な文字を に入れssます。

これにより、ストリームの最後に余分な文字が追加されます。これが唯一の問題かどうかはわかりませんが、おそらくその 1 つです。

編集:

さて、それを見た後、なぜそれが起こっているのか100%確信が持てませんが、それはあなたが stringstream を再利用しているためですss。コピーを行う前に呼び出すかss.seekp(0, ios::begin)、別の文字列ストリームを使用してください。

個人的には、 にコピーssする代わりに、入力ファイルから にgzipped直接書き込みgzipped、コピーを介して ss に出力します。

于 2013-01-23T18:53:25.280 に答える