How do I read a file into a std::string
, i.e., read the whole file at once?
Text or binary mode should be specified by the caller. The solution should b
This solution adds error checking to the rdbuf()-based method.
std::string file_to_string(const std::string& file_name)
{
std::ifstream file_stream{file_name};
if (file_stream.fail())
{
// Error opening file.
}
std::ostringstream str_stream{};
file_stream >> str_stream.rdbuf(); // NOT str_stream << file_stream.rdbuf()
if (file_stream.fail() && !file_stream.eof())
{
// Error reading file.
}
return str_stream.str();
}
I'm adding this answer because adding error-checking to the original method is not as trivial as you'd expect. The original method uses stringstream's insertion operator (str_stream << file_stream.rdbuf()
). The problem is that this sets the stringstream's failbit when no characters are inserted. That can be due to an error or it can be due to the file being empty. If you check for failures by inspecting the failbit, you'll encounter a false positive when you read an empty file. How do you disambiguate legitimate failure to insert any characters and "failure" to insert any characters because the file is empty?
You might think to explicitly check for an empty file, but that's more code and associated error checking.
Checking for the failure condition str_stream.fail() && !str_stream.eof()
doesn't work, because the insertion operation doesn't set the eofbit (on the ostringstream nor the ifstream).
So, the solution is to change the operation. Instead of using ostringstream's insertion operator (<<), use ifstream's extraction operator (>>), which does set the eofbit. Then check for the failiure condition file_stream.fail() && !file_stream.eof()
.
Importantly, when file_stream >> str_stream.rdbuf()
encounters a legitimate failure, it shouldn't ever set eofbit (according to my understanding of the specification). That means the above check is sufficient to detect legitimate failures.