c++ - 带有 Protocol Buffer 的 GzipOutputStream 和 GzipInputStream 的简单工作示例

标签 c++ gzip iostream protocol-buffers

在对 Protocol Buffers 进行了几天的试验后,我尝试 压缩文件。 使用 Python,这很容易做到,不需要任何游戏 与溪流。

因为我们的大部分代码都是用 C++ 编写的,所以我想压缩/ 解压相同语言的文件。我试过 boost 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 的示例使用 Protocol Buffers 但找不到工作 例子。

您现在可能已经注意到,我充其量只是流的初学者 并且非常感谢一个完整的工作示例,如 http://code.google.com/apis/protocolbuffers/docs/cpptutorial.html (我有我的地址簿,如何将它保存在 gzip 文件中?)

提前致谢。

编辑:工作示例。

示例 1 遵循 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; 
} 

关于 Google's Protobuf discussion group 的回答后的示例 2 :

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 文件): 示例 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%。

最佳答案

您的假设是正确的:您发布的代码不起作用,因为您是直接写入 ofstream 而不是通过 filtering_streambuf。要完成这项工作,您可以使用 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.
}

希望对您有所帮助!

关于c++ - 带有 Protocol Buffer 的 GzipOutputStream 和 GzipInputStream 的简单工作示例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7645041/

相关文章:

c++ - 使用引用计数逻辑 C++ 对 API 进行包装

c++ - 动态分配的对象是否默认初始化?

c++ - 如何使用可选的编译时参数声明模板函数?

java - 在 Java 中使用 Inflater 解压缩 gzip 数据

scala - 如何在 Scala 代码中读取压缩的 xml 文件?

linux - 在不知道文件名的情况下合并排序的文件

c++ - VS2010 中的 cout 分辨率

c++ - 在 iostream header 中使用静态数据

c++ - 从 std::streambuf 继承时出现不兼容的析构函数编译器警告

c++ - 特殊排序算法和通用签名