在C+中连续传输多个文件+; 我的问题与此类似,但我没有找到任何C++的引用。

在C+中连续传输多个文件+; 我的问题与此类似,但我没有找到任何C++的引用。,c++,c++11,C++,C++11,有一个要读取和处理的大文件列表。创建一个输入流的最佳方法是什么,该输入流可以逐个从文件中获取数据,并在上一个文件结束时自动打开下一个文件?该流将被提供给一个处理函数,该函数跨文件边界顺序读取可变大小的块 要获得一个简单的解决方案,请使用boost与文件的istream迭代器范围连接。我不知道当前C++库中的类似函数,但是在TS RangeSv3..P/>中可能存在一个函数。 你也可以自己写:写加入你自己是完全可能的 我将它写成一个“扁平化”的纯输入迭代器——一个范围内的迭代器,依次迭代每个范围的

有一个要读取和处理的大文件列表。创建一个输入流的最佳方法是什么,该输入流可以逐个从文件中获取数据,并在上一个文件结束时自动打开下一个文件?该流将被提供给一个处理函数,该函数跨文件边界顺序读取可变大小的块

要获得一个简单的解决方案,请使用
boost
与文件的istream迭代器范围连接。我不知道当前C++库中的类似函数,但是在TS RangeSv3..P/>中可能存在一个函数。 你也可以自己写:写加入你自己是完全可能的

我将它写成一个“扁平化”的纯输入迭代器——一个范围内的迭代器,依次迭代每个范围的内容。迭代器将跟踪范围的未来范围,以及当前元素的迭代器

是一个非常简单的zip迭代器,可以让您了解必须编写的代码的大小(zip迭代器是一个不同的概念,这是一个简单的迭代器,仅适用于
for(:)
循环)

这是如何使用C++14实现的示意图:

template<class It>
struct range_t {
  It b{};
  It e{};
  It begin() const { return b; }
  It end() const { return e; }
  bool empty() const { return begin()==end(); }
};

template<class It>
struct range_of_range_t {
  std::deque<range_t<It>> ranges;
  It cur;
  friend bool operator==(range_of_range_t const& lhs, range_of_range_t const& rhs) {
    return lhs.cur==rhs.cur;
  }
  friend bool operator!=(range_of_range_t const& lhs, range_of_range_t const& rhs) {
    return !(lhs==rhs);
  }
  void operator++(){
    ++cur;
    if (ranges.front().end() == cur) {
      next_range();
    }
  }
  void next_range() {
    while(ranges.size() > 1) {
      ranges.pop_front();
      if (ranges.front().empty()) continue;
      cur = ranges.front().begin();
      break;
    }
  }
  decltype(auto) operator*() const {
    return *cur;
  }
  range_of_range_t( std::deque<range_t<It>> in ):
    ranges(std::move(in)),
    cur{}
  {
    // easy way to find the starting cur:
    ranges.push_front({});
    next_range();
  }
};
模板
结构范围{
它是b{};
它是{};
它的begin()常量{return b;}
It end()常量{return e;}
bool empty()常量{return begin()==end();}
};
模板
结构范围{
标准::德克范围;
它是cur;
friend bool运算符==(范围常数和lhs的范围,范围常数和rhs的范围){
返回lhs.cur==rhs.cur;
}
friend bool运算符!=(范围常数和lhs的范围常数和rhs的范围常数和rhs的范围常数){
返回!(lhs==rhs);
}
void运算符++(){
++cur;
if(ranges.front().end()==cur){
下一个_范围();
}
}
无效下一个_范围(){
while(ranges.size()>1){
ranges.pop_front();
如果(ranges.front().empty())继续;
cur=ranges.front().begin();
打破
}
}
decltype(自动)运算符*()常量{
返回*cur;
}
范围(std::deque in):
范围(标准::移动(输入)),
cur{}
{
//找到起始电流的简单方法:
范围。向前推({});
下一个_范围();
}
};
迭代器需要工作,因为它应该支持所有迭代器公理。要正确使用末端迭代器需要做一些工作


这不是一个strema,而是一个迭代器。

您要做的是提供一个继承自的类型。有许多神秘的
virtual
成员函数,其中与您相关的有
showmanyc()
underflow()
uflow()
xsgetn()
。您需要将它们重载,以便在溢出时自动打开列表中的下一个文件(如果有)

下面是一个示例实现。我们充当一个
std::filebuf
,只需保留下一个需要读取的文件的
deque

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;
};

“Unixy”的方法是将您的程序编写为一个过滤器(即,它从stdin读取并写入stdout),然后使用现有的构建块,如
cat input\u file*.dat | myprogram
。但是没有更多的细节(例如,文件是否都在一个目录中,并且名称是全局的,或者它们分布在不同的地方,或者顺序需要不同),很难说得更多……您可以创建一个从
std::istream
派生的新类,该类包含
std::ifstream
std::vector
,该类在EOF或读取失败时自动切换到下一个,将它们收集到缓冲区文件中,然后读取它们?因此,2部分的操作,这些问题将在下一个问题中被描述,我会问那些声称知道C++的所有人。好发现@卡布森诺尔甚至开始研究如何制作一个有效的例子。我想这个案例还不错,只需要
underflow()
multifilebuf mfb{"file1", "file2", "file3"};

std::istream is(&mfb);
std::string word;
while (is >> word) {
    // transaparently read words from all the files
}