Reputation: 368
I'm trying to merge two files into one by simply using rdbuf(), but when merged, the file's first line is missing. The code is below:
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();
}
}
Upvotes: 0
Views: 804
Reputation: 44063
Well, you pull out the first line of each file before concatenating the rest of them, so that's expected. You still have the lines, though, so simply print them in between:
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();
}
Addendum: @BenVoigt rightly notes that if one of the files contains a single line that does not end with a newline, the output of this will be different from printing the plain file contents delimited by a single newline (there will be an extra newline in the middle or at the end).
On the basis that this case is recognizable because the first getline
call will have set the end-of-file flag, this can be avoided as follows:
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(); }
}
Since this is something of a mouthful and repetitive, I'd consider using a lambda to make it more concise:
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);
}
For regular files like these, seeking back is also a possibility, but I feel that it is better to avoid giving up the ability to use code on pipes, sockets and other non-seekable streams without a compelling reason even if it seems like an unlikely use case.
Upvotes: 2
Reputation: 283733
file3 << filen.rdbuf()
Copies from the current position in the filen
stream forward, into file3
. The current position is after the first line, since you just read it.
Seek back to the beginning and your missing line will be missing no longer.
Upvotes: 1