rdbuf()奇怪的行为

时间:2015-02-25 22:00:54

标签: c++ string file buffer

我试图通过简单地使用rdbuf()将两个文件合并为一个,但是当合并时,文件的第一行丢失了。代码如下:

void mergeFiles(ifstream &file1, ifstream &file2, ofstream &file3) {

    int num1;
    int num2;

    string firstLine_1;
    string firstLine_2;

    getline(file1, firstLine_1);
    num1 = atoi(firstLine_1.c_str());

    getline(file2, firstLine_2);
    num2 = atoi(firstLine_2.c_str());

    if (num1<num2) {
        file3 << file1.rdbuf() << "\n" << file2.rdbuf();
    } else {
        file3 << file2.rdbuf() << "\n" << file1.rdbuf();
    }
}

2 个答案:

答案 0 :(得分:2)

好吧,在连接其余文件之前,先拉出每个文件的第一行,这样就可以了。但是你仍然有线条,所以只需在它们之间打印:

if (num1<num2) {
    file3 << firstLine_1   << "\n"
          << file1.rdbuf() << "\n"
          << firstLine_2   << "\n"
          << file2.rdbuf();
} else {
    file3 << firstLine_2   << "\n"
          << file2.rdbuf() << "\n"
          << firstLine_1   << "\n"
          << file1.rdbuf();
}

附录: @BenVoigt正确地指出,如果其中一个文件包含一行不以换行符结尾,则此输出将与打印由a分隔的纯文件内容不同单个换行符(中间或末尾会有一个额外的换行符)。

基于这种情况是可识别的,因为第一个getline调用将设置文件结束标志,这可以避免如下:

if (num1<num2) {
    file3 << firstLine_1;
    if(file1) { file3 << "\n" << file1.rdbuf(); }
    file3 << "\n";
    file3 << firstLine_2;
    if(file2) { file3 << "\n" << file2.rdbuf(); }
} else {
    file3 << firstLine_2;
    if(file2) { file3 << "\n" << file2.rdbuf(); }
    file3 << "\n";
    file3 << firstLine_1;
    if(file1) { file3 << "\n" << file1.rdbuf(); }
}

由于这是一种口感和重复的东西,我考虑使用lambda使其更简洁:

auto printfile = [&file3](std::string const &firstline, std::istream &in) {
  file3 << firstline;
  if(in) { file3 << "\n" << in.rdbuf(); }
};

if(num1 < num2) {
  printfile(firstLine_1, file1);
  file3 << "\n";
  printfile(firstLine_2, file2);
} else {
  printfile(firstLine_2, file2);
  file3 << "\n";
  printfile(firstLine_1, file1);
}

对于像这样的常规文件,回寻也是一种可能性,但我觉得最好避免放弃在管道,套接字和其他不可搜索的流上使用代码的能力,即使看起来没有令人信服的理由就像一个不太可能的用例。

答案 1 :(得分:1)

file3 << filen.rdbuf()

filen流中的当前位置转发到file3。当前位置在第一行之后,因为您刚读完它。

回到开头,你的遗失线将不复存在。