C++ course menu
C++ File Handling: Reading and Writing Files with fstream
Learn file I/O in C++: writing with std::ofstream, reading line by line with std::ifstream and getline, appending, checking that a file opened, parsing CSV data, reading numbers, binary files, and working with paths using std::filesystem.
On this page
Programs often need to save data and load it later: settings, logs, reports, scores. C++ reads and writes files with file streams from <fstream>, which work just like std::cout and std::cin:
Writing a file#
#include <fstream>
#include <iostream>
int main() {
std::ofstream out("scores.txt");
if (!out) {
std::cout << "Could not open the file\n";
return 1;
}
out << "Asha 92\n";
out << "Ravi 85\n";
out << "Meera 78\n";
std::cout << "Saved\n";
} // out is closed automatically hereSaved- Creating an
std::ofstreamopens the file, creating it if it does not exist and replacing its contents if it does. <<writes exactly as withstd::cout.- The file is closed automatically when the stream object is destroyed (RAII), so calling
close()is optional.
Reading line by line#
std::getline reads one line at a time, and returns a value that tests false at the end of the file:
#include <fstream>
#include <iostream>
#include <string>
int main() {
{
std::ofstream out("notes.txt");
out << "Buy milk\nCall Ravi\nFinish C++ lesson\n";
}
std::ifstream in("notes.txt");
if (!in) {
std::cout << "notes.txt not found\n";
return 1;
}
std::string line;
int number = 1;
while (std::getline(in, line)) {
std::cout << number++ << ". " << line << '\n';
}
}1. Buy milk
2. Call Ravi
3. Finish C++ lessonwhile (std::getline(in, line)) is the standard loop for reading text files. Avoid while (!in.eof()), which runs one extra time after the last line.
Reading values with >>#
>> reads whitespace-separated values and converts them, just like std::cin:
#include <fstream>
#include <iostream>
#include <string>
int main() {
{
std::ofstream out("scores.txt");
out << "Asha 92\nRavi 85\nMeera 78\n";
}
std::ifstream in("scores.txt");
std::string name;
int score = 0;
int total = 0;
int count = 0;
while (in >> name >> score) {
total += score;
++count;
}
std::cout << count << " students, average " << static_cast<double>(total) / count << '\n';
}3 students, average 85Appending#
Open with std::ios::app to add to the end of a file instead of replacing it, which is what log files need:
#include <fstream>
#include <iostream>
#include <string>
void log(const std::string& message) {
std::ofstream out("app.log", std::ios::app);
out << message << '\n';
}
int main() {
std::ofstream("app.log"); // start with an empty file
log("started");
log("processing");
log("finished");
std::ifstream in("app.log");
std::string line;
while (std::getline(in, line)) std::cout << line << '\n';
}started
processing
finishedCombine flags with |, for example std::ios::out | std::ios::app.
Parsing CSV data#
Comma-separated files are read line by line, then split with std::getline on a std::stringstream:
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
int main() {
{
std::ofstream out("sales.csv");
out << "region,amount\nNorth,1200\nSouth,800\nNorth,450\nEast,990\n";
}
std::ifstream in("sales.csv");
std::string line;
std::getline(in, line); // skip the header row
std::map<std::string, int> totals;
while (std::getline(in, line)) {
std::stringstream row(line);
std::string region;
std::string amount;
std::getline(row, region, ',');
std::getline(row, amount, ',');
totals[region] += std::stoi(amount);
}
for (const auto& [region, total] : totals) {
std::cout << region << ": " << total << '\n';
}
}East: 990
North: 1650
South: 800This simple approach does not handle quoted fields that contain commas; real-world CSV files with such data need a proper CSV library.
Checking for errors#
A stream that failed to open, or hit bad data, tests as false. Always check after opening. If you prefer exceptions, ask the stream to throw:
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("does-not-exist.txt");
if (!in.is_open()) {
std::cout << "Could not open does-not-exist.txt\n";
}
std::ifstream strict;
strict.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
strict.open("does-not-exist.txt");
} catch (const std::ios_base::failure&) {
std::cout << "Exception: open failed\n";
}
}Could not open does-not-exist.txt
Exception: open failedstd::filesystem: working with paths#
C++17's <filesystem> handles files and folders: checking existence, sizes, creating directories, listing contents and building paths portably:
#include <filesystem>
#include <fstream>
#include <iostream>
namespace fs = std::filesystem;
int main() {
fs::create_directories("reports/2026");
fs::path file = fs::path("reports") / "2026" / "summary.txt";
std::ofstream(file, std::ios::binary) << "Total: 5400\n";
std::cout << std::boolalpha << fs::exists(file) << '\n';
std::cout << file.filename().string() << ' ' << file.extension().string() << '\n';
std::cout << fs::file_size(file) << " bytes\n";
fs::remove_all("reports");
std::cout << fs::exists("reports") << '\n';
}true
summary.txt .txt
12 bytes
falseThe / operator joins path parts with the correct separator for the operating system.
The file is opened in binary mode so that its size is the same everywhere. In text mode, Windows writes each \n as two characters (\r\n), so the same text would take 13 bytes on Windows and 12 on macOS and Linux.
Common mistakes#
Practice#
Practice exercise
Write five words to words.txt, one per line: apple, kiwi, banana, fig, cherry. Then read the file back and print the longest word and the total number of characters.
Show solution
#include <fstream>
#include <iostream>
#include <string>
int main() {
{
std::ofstream out("words.txt");
for (const char* w : {"apple", "kiwi", "banana", "fig", "cherry"}) {
out << w << '\n';
}
}
std::ifstream in("words.txt");
std::string word;
std::string longest;
std::size_t total = 0;
while (std::getline(in, word)) {
total += word.size();
if (word.size() > longest.size()) longest = word;
}
std::cout << "Longest: " << longest << '\n';
std::cout << "Characters: " << total << '\n';
}Longest: banana
Characters: 24banana and cherry are both 6 letters; using > keeps the first one found.
Key takeaway#
Finished this lesson?