【问题标题】:Split ifstream in n streams?在n个流中拆分ifstream?
【发布时间】:2020-05-23 16:07:36
【问题描述】:

我的 ifstream 有问题。我想将 ifstream 分成 n 个部分。

例如 n = 3:

  1. Ifstream 包含文件的前 1/3。
  2. Ifstream 包含文件的后 1/3。
  3. Ifstream 包含文件的第三个 1/3。
    std::ifstream in("test.txt");
    std::vector<std::string> v1;
    std::vector<std::string> v2;
    std::vector<std::string> v3;

    //first 1/3 of file
    read(in, v1);
    //second 1/3 of file
    read(in, v2);
    //third 1/3 of file
    read(in, v3);

    read(in, v){

         std::string line {""};
         while(getline(in, line)){
              v.pushback(line);
         }
    }

【问题讨论】:

  • 对不起,有很多方法。你想返回 3 个 ifstreams,你只想做 3 次读取吗?需要更多细节。
  • 我想从流中的某些点读取 3 次
  • 所以有 seekg() 和 tellg() 方法,可以帮助你找出文件的大小(以字节为单位),然后返回读取并测试是否达到了 1/3 或2/3。它们不会是准确的,因为这些行可能不会完全拆分文件。如果您想按行数拆分它,只能通过将整个文件读入一个行向量然后拆分该向量来完成。
  • 问题是我无法在 read() 内部操作或更改参数。有没有办法只通过 2/3 的 ifstream?
  • 然后创建三个 ifstream。获取文件的大小。将第二个 ifstream 查找到文件的 1/3,将第三个 ifstream 查找到文件的 2/3。是的,你必须创建 3 个单独的 ifstream,因为 ifstream 只能有一个状态并且不能被复制。

标签: c++ stream ifstream istream seekg


【解决方案1】:

@Mandy007 向您展示了一种简单的方法,将所有内容预读到内存中。

“干净”的方法是定义一个streambuf派生类,它将读取请求委托给底层istream,但操纵查找位置和文件结束指示使其看起来像文件的区域是一个完整的流。

这就是 iostream 库中自定义的工作方式……流类本身不是多态的,所有行为都来自 streambuf 实例。

【讨论】:

    【解决方案2】:

    您可以读取并推送向量中的所有行,然后将向量拆分为 3 部分,例如:

    std::string s;
    while(!in.eof() && getline(in, s)) v1.push_back(s);
    int size = v1.size(), itv2 = 0, itv3 = 0, chunk = v1.size()/3;
    for(unsigned i = size-1; i >= size/3; --i, v1.pop_back()) 
        (i > chunk*2)? v3[chunk-itv3++] = v1[i] : v2[chunk-itv2++] = v1[i]; 
    

    现在如果你想对 n 个分区执行此操作,你可以这样做:

    //n must be defined before use
    std::vector<std::vector<std::string> > vChunks(n+1);
    std::vector<std::string> v;
    std::string s;
    while(!in.eof() && getline(in, s)) v.push_back(s);
    int size = v.size(), chunk = v.size()/n, r = v.size()%n;
    vChunks[n].resize(r);
    for(int i = 0; i < n; i++)
        vChunks[i].resize(chunk);
    for(int i = v.size()-1, it =1; it <= r; it++, --i, v.pop_back())
        vChunks[n][r-it] = v[i];
    for(int i = v.size()-1; i >= 0; --i, v.pop_back())
        vChunks[(i%chunk == 0)? (i-1)/chunk : i/chunk][i%chunk] = v[i];
    

    其中vChunks 前 n 个分区具有 n 维之间的行数,并且在 n + 1 中具有最后一行的维数,如果它不能被总行数 n 整除

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      • 2011-04-28
      • 1970-01-01
      • 2019-01-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多