2011-10-04 8 views
7

después de algunos días de experimentar con Buffers de Protocolo intenté comprimir los archivos . Con Python esto es bastante simple de hacer y no requiere ningún juego con transmisiones.Ejemplo de trabajo simple de GzipOutputStream y GzipInputStream con Buffers de Protocolo

Como la mayoría de nuestro código está escrito en C++, me gustaría comprimir/ descomprimir archivos en el mismo idioma. He intentado la biblioteca gzip impulso, pero no pude conseguir que funcione (no comprimir):

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

He buscado ejemplos que utilizan GzipOutputStream and GzipInputStream con Protocol Buffers pero no pude encontrar una ejemplo de trabajo.

Como podrá darse cuenta por ahora soy un principiante en el mejor de arroyos y apreciaría realmente un ejemplo completamente de trabajo como en http://code.google.com/apis/protocolbuffers/docs/cpptutorial.html (tengo mi address_book, ¿Cómo se guardan en un archivo gziped?)

Gracias de antemano.

EDITAR: Ejemplos de trabajo.

Ejemplo 1 después de la respuesta aquí en 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; 
} 

Ejemplo 2 siguiente respuesta en Google's Protobuf discussion group:

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

Algunos comentarios sobre el rendimiento (lectura formato actual y redactar protobuf 11146 archivos): Ejemplo 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) 

Ejemplo 2:

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

Parece que el método de Google utiliza la CPU de manera más eficiente, es ligeramente más rápido (aunque espero que esto sea dentro de la precisión) y produce un conjunto de datos ~ 7% más pequeño con el mismo ajuste de compresión.

+0

Tenga en cuenta que el problema fundamental aquí no está relacionado con los búferes de protocolo, cualquier ejemplo de "escribir/ejecutar gzip a través de una secuencia" debería funcionar. –

Respuesta

2

Su suposición es correcta: el código que publicó no funciona porque está escribiendo directamente en el ofstream en lugar de en el filtering_streambuf. Para realizar este trabajo se puede utilizar en lugar 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. 
} 

O más brevemente, utilizando 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. 
} 

espero que esto ayude!

+0

Gracias! Esto de hecho ayudó. Ahora está funcionando como debería. – DragonTux

Cuestiones relacionadas