Step 5 of 6
Writing files with ofstream
std::ofstream writes a file with <<. By default opening it truncates: the old contents are thrown away, like "w" in C's fopen. Pass std::ios::app to append to the end instead.
#include <fstream>
#include <iostream>
#include <string>
bool log_line(const std::string& path, const std::string& msg) {
std::ofstream out(path, std::ios::app);
out << msg << "\n";
return static_cast<bool>(out); // false if the open or the write failed
}
int main() {
std::ofstream("log.txt") << "start\n"; // truncate and write one line
log_line("log.txt", "round 1");
log_line("log.txt", "round 2");
std::ifstream in("log.txt");
std::string line;
while (std::getline(in, line)) std::cout << line << "\n";
std::cout << log_line("no_such_dir/log.txt", "x") << "\n";
}
start
round 1
round 2
0
How it works
- Every
log_linecall opens the file in append mode, adds one line and closes it again whenoutis destroyed. - The last call fails because the folder doesn't exist, and the function reports that by returning
false(printed as0). static_cast<bool>(out)asks the stream "did everything so far succeed?". A stream remembers failures, so checking once at the end covers the open and every write.
Why check after writing?
Opening can succeed and a later write can still fail: the disk fills up, a USB stick is removed, a quota is exceeded. If the data matters, check the stream after writing, and report failure to the caller rather than pretending all is well.
Common mistakes
- Forgetting
std::ios::appand wiping a log every time the program starts. - Writing a file and reading it back in the same scope while the
ofstreamis still open. Its data may still be in a buffer. Let it go out of scope (or callflush()) first.
Your turn: write bool save_scores(const std::string& path, const std::map<std::string, int>& scores) that writes one name=score line per entry (the map's order), replacing any existing file. Return whether everything succeeded.
Previous: Reading files with ifstream Next: Challenge: operator>> for your own type