我的问题与此类似,但我没有找到任何有关此问题的 C++ 参考资料。
有一个要读取和处理的大文件列表。创建一个输入流的最佳方法是什么,该输入流可以逐个从文件中获取数据,并在上一个文件结束时自动打开下一个文件?该流将被提供给处理函数,该处理函数跨文件边界顺序读取可变大小的块。
您需要做的是提供一个继承自 的类型std::basic_streambuf。有许多神秘的virtual成员函数,与您相关的函数是showmanyc()、underflow()、uflow()和xsgetn()。您需要重载它们,以便在溢出时自动打开列表中的下一个文件(如果有)。
这是一个示例实现。我们充当std::filebuf并只保留deque<string>我们需要读取的下一个文件:
class multifilebuf : public std::filebuf
{
public:
multifilebuf(std::initializer_list<std::string> filenames)
: next_filenames(filenames.begin() + 1, filenames.end())
{
open(*filenames.begin(), std::ios::in);
}
protected:
std::streambuf::int_type underflow() override
{
for (;;) {
auto res = std::filebuf::underflow();
if (res == traits_type::eof()) {
// done with this file, move onto the next one
if (next_filenames.empty()) {
// super done
return res;
}
else {
// onto the next file
close();
open(next_filenames.front(), std::ios::in);
next_filenames.pop_front();
continue;
}
}
else {
return res;
}
}
}
private:
std::deque<std::string> next_filenames;
};
Run Code Online (Sandbox Code Playgroud)
这样,您就可以使一切对最终用户透明:
multifilebuf mfb{"file1", "file2", "file3"};
std::istream is(&mfb);
std::string word;
while (is >> word) {
// transaparently read words from all the files
}
Run Code Online (Sandbox Code Playgroud)