2011-10-04 21 views
7

プロトコルバッファを実験して数日後に私は ファイルを圧縮しようとしました。 Pythonの場合、これは非常に簡単で、ストリームを使用して再生する必要はありません。 プロトコルバッファを使ったGzipOutputStreamとGzipInputStreamの簡単な使用例

私たちのコードのほとんどはC++で書かれているので、/ は同じ言語でファイルを圧縮解除したいと思います。私はブーストのgzipライブラリを試してみたが、それは仕事を得ることができませんでした(圧縮しない):

int writeEventCollection(HEP::MyProtoBufClass* protobuf, std::string filename, unsigned int compressionLevel) { 
      ofstream file(filename.c_str(), ios_base::out | ios_base::binary); 
      filtering_streambuf<output> out; 
      out.push(gzip_compressor(compressionLevel)); 
      out.push(file); 
      if (!protobuf->SerializeToOstream(&file)) {//serialising to wrong stream I asume 
        cerr << "Failed to write ProtoBuf." << endl; 
        return -1; 
      } 
      return 0; 
    } 

私はプロトコルバッファとGzipOutputStream and GzipInputStreamを利用例については、検索したが、作業 例を見つけることができませんでした。

あなたはおそらく今、私はストリーム でせいぜい初心者ですし、本当に http://code.google.com/apis/protocolbuffers/docs/cpptutorial.html のように完全に動作する例をいただければ幸いです(私はgzipedファイルに保存しますか、私のaddress_bookを持っている?)で気づいたよう

ありがとうございます。

EDIT:作業例。

int writeEventCollection2(shared_ptr<HEP::EventCollection> 
eCollection, std::string filename, 
         unsigned int compressionLevel) { 
using namespace google::protobuf::io; 
int filedescriptor = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 
       S_IREAD | S_IWRITE); 
if (filedescriptor == -1) { 
         throw "open failed on output file"; 
       } 
google::protobuf::io::FileOutputStream file_stream(filedescriptor); 
GzipOutputStream::Options options; 
options.format = GzipOutputStream::GZIP; 
options.compression_level = compressionLevel; 
google::protobuf::io::GzipOutputStream gzip_stream(&file_stream, 
options); 
if (!eCollection->SerializeToZeroCopyStream(&gzip_stream)) { 
    cerr << "Failed to write event collection." << endl; 
    return -1; 
    } 
close(filedescriptor); 
return 0; 
} 

パフォーマンス上のいくつかのコメントを(現在のフォーマットを読み書きいるProtobuf 11146ファイル):Google's Protobuf discussion groupに答え、次の例2のStackOverflow

int writeEventCollection(shared_ptr<HEP::EventCollection> eCollection, 
std::string filename, unsigned int compressionLevel) { 
filtering_ostream out; 
out.push(gzip_compressor(compressionLevel)); 
out.push(file_sink(filename, ios_base::out | ios_base::binary)); 
if (!eCollection->SerializeToOstream(&out)) { 
       cerr << "Failed to write event collection." << endl; 
       return -1; 
} 

return 0; 
} 

ここで答えを以下の

例1 例1:

real 13m1.185s 
user 11m18.500s 
sys  0m13.430s 
CPU usage: 65-70% 
Size of test sample: 4.2 GB (uncompressed 7.7 GB, our current compressed format: 7.7 GB) 

例2:

real 12m37.061s 
user 10m55.460s 
sys  0m11.900s 
CPU usage: 90-100% 
Size of test sample: 3.9 GB 

Googleの方法は、より効率的にCPUを使用しているようだ、わずかに速いです(私は、これは精度の範囲内であることを期待していないが)と同じ圧縮設定で〜7%小さいデータセットを生成します。

+0

ここでの基本的な問題は、プロトコルバッファに関するものではなく、 "ストリーム経由の書き込み/チェーンgzip"の例が有効であることに注意してください。 –

答えて

2

あなたの前提は正しいです:filtering_streambufの代わりにofstreamに直接書いているので、送信したコードは機能しません。この作品を作るためには、代わりにfiltering_ostreamを使用することができます。

ofstream file(filename.c_str(), ios_base::out | ios_base::binary); 
filtering_ostream out; 
out.push(gzip_compressor(compressionLevel)); 
out.push(file); 

if (!protobuf->SerializeToOstream(&out)) { 
    // ... etc. 
} 

以上簡潔に、file_sinkを使用して:

filtering_ostream out; 
out.push(gzip_compressor(compressionLevel)); 
out.push(file_sink(filename, ios_base::out | ios_base::binary)); 

if (!protobuf->SerializeToOstream(&out)) { 
    // ... etc. 
} 

私はこれが役に立てば幸い!

+0

ありがとう!これは確かに助けになりました。それは今のように動作しています。 – DragonTux

関連する問題