我想要格式化和输出一些数据,无论是在原始文本文件还是.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是可能的吗?你会改变什么?
由于
编辑:如果我切换到常规指针而不是共享指针,并且在文件之前明确删除流,则它可以正常工作。
答案 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类的包装器得到支持
此
此解决方案的优势在于一切都得到保证 以正确的嵌套顺序构造和破坏, 因为没有动态分配可以允许 任意顺序。