Given this:
auto f = std::ifstream{file};
if (f) {
std::stringstream stream;
stream << f.rdbuf();
return stream.str();
}
return std::string{};
I don't see why it works. I don't know what type f is, because it says auto, but apparently you can check that for non-zero-ness. But when the file is large, like 2 gig, the delay in running happens in this line:
stream << f.rdbuf();
The documentation says rdbuf() gets you the pointer to the ifstream's internal buffer. So in order for it to read the entire file, the buffer would have to size the file, and load it all in in one shot. But by the time the stream << happens, rdbuf() has to already be set, or it won't be able to return a point. I would expect the constructor to do that in this case, but it's obviously lazy loaded, because reading in the entire file on construction would be bad for every other use case, and the delay is in the stream << command.
Any thoughts? All other stack overflow references to reading in a file to a string always loop in some way.
If there's some buffer involved, which obviously there is, how big can it get? What if it is 1 byte, it would surely be slow.
Adorable c++ is very opaque, bad for programmers who have to know what's going on under the covers.
It's a function of how operator<<
is defined on ostream
s when the argument is a streambuf
. As long as the streambuf
isn't a null pointer, it extracts characters from the input sequence controlled by the streambuf
and inserts them into *this
until one of the following conditions are met (see operator<<
overload note #9):
- end-of-file occurs on the input sequence;
- inserting in the output sequence fails (in which case the character to be inserted is not extracted);
- an exception occurs (in which case the exception is caught).
Basically, the ostream
(which stringstream
inherits from) knows how to exercise a streambuf
to pull all the data from the file it's associated with. It's an idiomatic, but as you note, not intuitive, way to slurp a whole file. The streambuf
isn't actually buffering all the data here (as you note, reading the whole file into the buffer would be bad in the general case), it's just that it has the necessary connections to adjust the buffered window as an ostream
asks for more (and more, and more) data.
if (f)
works because ifstream
has an overload for operator bool
that is implicitly invoked when the "truthiness" of the ifstream
is tested that tells you if the file is in a failure state.