c++ - 从函数返回 boost streambuf
问题描述
我正在尝试将读取 gz 文件的代码包装成一个函数,源代码取自https://techoverflow.net/2013/11/03/c-iterating-lines-in-a-gz-file-using -boostiostreams/
我的尝试
boost::iostreams::filtering_streambuf<boost::iostreams::input> func(std::string filename);
boost::iostreams::filtering_streambuf<boost::iostreams::input> func(std::string filename)
{
std::ifstream file(filename, std::ios_base::in | std::ios_base::binary);
boost::iostreams::filtering_streambuf<boost::iostreams::input> inbuf;
inbuf.push(boost::iostreams::gzip_decompressor());
inbuf.push(file);
return inbuf;
}
void mymainfunc(std::string filename)
{
//Convert streambuf to istream
std::istream ifstrm( func( filename));
std::string line;
while(std::getline(ifstrm, line)) {
std::cout << line << std::endl;
}
}
如果没有通过函数运行代码运行良好,我认为我在返回类型中做错了。错误:https ://pastebin.com/kFpjYG0M
解决方案
流不可复制。事实上,这个过滤流缓冲区甚至是不可移动的。
因此,在这种情况下,您将希望通过智能指针动态分配和返回。但是,即使只是返回过滤流缓冲区也行不通,因为它会保存对 ifstream 的引用。那是当地人。
所以,也许你需要把它打包起来:
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <fstream>
namespace bio = boost::iostreams;
struct MySource {
using fisb = bio::filtering_istreambuf;
struct State {
State(std::string filename) : ifs(filename, std::ios::binary) {
buf.push(bio::gzip_decompressor());
buf.push(ifs);
}
fisb buf;
std::ifstream ifs;
std::istream is { &buf };
};
std::unique_ptr<State> _state;
operator std::istream&() const { return _state->is; }
};
MySource func(std::string filename) {
auto inbuf = std::make_unique<MySource::State>(filename);
return {std::move(inbuf)};
}
#include <iostream>
void mymainfunc(std::string filename)
{
auto source = func(filename);
std::istream& is = source;
std::string line;
while(std::getline(is, line)) {
std::cout << line << std::endl;
}
}
int main(){
mymainfunc("test.cpp.gz");
}
替代#1
您可以简化:
struct MySource {
struct State {
State(std::string filename) : ifs(filename, std::ios::binary) {
is.push(bio::gzip_decompressor());
is.push(ifs);
}
std::ifstream ifs;
bio::filtering_istream is;
};
std::unique_ptr<State> _state;
operator std::istream&() const { return _state->is; }
};
不单独处理流缓冲区使其更简单。
替代#2
不复制整个东西有它自己的优雅:
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/filter/gzip.hpp>
#include <fstream>
#include <iostream>
void mymainfunc(std::istream& is) {
std::string line;
while(std::getline(is, line)) {
std::cout << line << std::endl;
}
}
namespace bio = boost::iostreams;
int main(){
std::ifstream ifs("test.cpp.gz", std::ios::binary);
bio::filtering_istream is;
is.push(bio::gzip_decompressor());
is.push(ifs);
mymainfunc(is);
}
推荐阅读
- python - 语音识别并没有证明我有不同俚语英语的全文
- xml - ISO20022 消息模式节点搜索指定路径
- list - 运行此序言代码时显示错误
- javascript - mongoose 与数据库的连接代码不起作用。=> mongoose.connection.once()
- c++ - 有人可以解释为什么我的功能“超出范围”吗?
- python - django-admin 无法创建项目,因为 - zsh: /usr/local/bin/django-admin: bad interpreter
- python - 保存/存储数据 discord.py
- javascript - 在 JavaScript 中创建复制函数
- java - kotlin 协程是如何在底层实现的?
- xaml - 为什么我在 Xamarin iOS 中的网格高度超过手机大小