2011-10-04 2 views
7

프로토콜 버퍼를 실험 한 지 얼마되지 않아 파일을 압축하려고했습니다. 파이썬을 사용하면 매우 간단하며 스트림이있는 재생 을 필요로하지 않습니다.프로토콜 버퍼를 사용한 GzipOutputStream 및 GzipInputStream의 간단한 예제

대부분의 코드는 C++로 작성되었으므로/ 같은 언어로 파일의 압축을 풀고 싶습니다. 나는 부스트 GZIP 라이브러리를 시도했지만, (압축되지 않음) 작동 가져올 수 없습니다 : 내가 프로토콜 버퍼와 GzipOutputStream and GzipInputStream을 활용 예제를 검색했지만 작업 예를 찾을 수 없습니다

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; 
    } 

. 당신은 아마 지금 쯤 눈치

나는 초보자는 기껏 스트림 와 오전 것 정말 같이 완전히 동작하는 예제 감사 http://code.google.com/apis/protocolbuffers/docs/cpptutorial.html (나는 내가 gziped 파일에 저장 어떻게 내 address_book이?)

미리 감사드립니다.

편집 : 실습 예제.

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 11,146 파일) : 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 

은 구글의 방법은 (내가이 정도 내에있을 것으로 예상하지만) 약간 빠르게,보다 효율적으로 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