C ++ 11 boost :: iostreams :: filtering_stream删除

时间:2013-08-13 11:08:46

标签: c++ boost c++11 gzip boost-iostreams

我想要格式化和输出一些数据,无论是在原始文本文件还是.gz压缩文本文件中。

因此,我想做这样的事情:

shared_ptr<ofstream> file = make_shared<ofstream>(filename.c_str());
shared_ptr<ostream> stream;
if (compressed) {
    stream = getCompressedStream(*file);
} else {
    stream = std::move(file);
}

for (auto c = data.begin(); c != data.end(); ++c) {
    *stream << **c << "\t" << (*c)->getThing() << endl;
}

getCompressedStream是一个解密流并返回新的非加密流的函数:

std::unique_ptr<std::ostream> getCompressedStream(std::ofstream& file)
{
    typedef io::filtering_ostream filter;
    std::unique_ptr<filter> out = std::unique_ptr<filter> (new filter());
    out->push(io::gzip_compressor());
    out->push(file);
    return std::move(out);
}

所以我希望getCompressedStream抽象调用boost lib,所以我只在主程序中使用std流。

它不起作用:.gz文件已损坏/无法读取。

根据这个thread,filtering_stream的输出是在对象的销毁中完成的。因此,我不知道是否可以使用shared_ptr干净地完成它。我不知道文件或流是否首先被破坏,我想这会导致问题。

你认为以这种方式实现getCompressedStream是可能的吗?你会改变什么?

由于

编辑:如果我切换到常规指针而不是共享指针,并且在文件之前明确删除流,则它可以正常工作。

1 个答案:

答案 0 :(得分:0)

我不确定。真正的问题是你永远不会明确 关闭ofstream,所以你不知道发生了什么 上。 (除非是例外情况,否则你会去 无论如何删除新文件,你必须检查的状态 关闭后ofstream对象,知道是否一切 成功与否。)更一般地说,你的解决方案似乎过于成功 对我来说很复杂;你试图在一个单一的过程中做太多 功能。我通常这样做的方式(用我自己的过滤 streambuf,早在几年前的推进版本之前)就是 做类似的事情:

std::ofstream file( filename.c_str() );
if ( compressed ) {
    CompressedStreambuf c( file );
    outputData( file );
} else {
    outputDate( file );
}
file.close();
if ( !file ) {
    remove( filename.c_str() );   //  Since it isn't complete
    //  Ensure that program return code is failure.
}

当然,我自己的过滤streambuf工作略有不同 而不是boost:构造函数采用ostream插入 ostream前面的过滤器,析构函数刷新 并删除过滤器(RAII的变体)。但它不应该 太难以使Boost类的包装器得到支持 此

此解决方案的优势在于一切都得到保证 以正确的嵌套顺序构造和破坏, 因为没有动态分配可以允许 任意顺序。