Reputation: 385
I've noticed that using .rdbuf()
on an ifstream
seems to change it somehow. The following code should show the problem.
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
ifstream ifs("Sample.csv");
cout << "Reading buffer: " << endl;
cout << ifs.rdbuf(); // Outputs buffer as expected
cout << "Reading buffer again: " << endl;
cout << ifs.rdbuf(); // Returns nothing
return 0;
}
The reason this is bothering me is that I'm currently trying to copy the contents of one text file into another using ofstream ofs; ofs << ifs.rdbuf()
. This works fine but makes reading from ifs
using getline(ifs, str)
fail, effectively "breaking" the stream.
Upvotes: 2
Views: 2282
Reputation: 385
ifs.rdbuf()
returns a pointer to the ifs
's corresponding stream buffer object. Sending it to std::cout
via <<
overload pulls information from the stream until the end of the buffer is reached (eof
). Calling .rdbuf()
again returns "nothing" because there's nothing to read at the end of the buffer. The buffer seek position be explicitly reset to zero by calling ifs.seekg (0);
.
Upvotes: 3
Reputation: 385264
This isn't particularly "weird"; it's the same stream behaviour you see every day. rdbuf
isn't like std::stringstream::str()
and it isn't magic — it's a pointer to the buffer, that your cout
is then reading from just as you would read from the original stream yourself:
std::stringstream ss("1");
int x;
if (ss >> x)
cout << x;
if (ss >> x) // doesn't work a second time; "1" is already extracted
cout << x;
As your stream is a file stream, you can seek it back to the beginning to start from scratch (which will inherently do the same to its underlying buffer).
Upvotes: 3