🧬 Phase 5 · Templates & Advanced 🟡 Intermediate MODULE 22

File I/O — Reading & Writing Files

⏱️ 20 min read
📖 Theory + Code
🧩 5 Quiz Questions
🏗️ 1 Challenge
Your progress in Phase 575%
🎯 What you'll learn: The <fstream> header, writing files with std::ofstream, reading them back with std::ifstream using both getline() and >>, and a complete worked example that writes several lines to a file and then reads them straight back.

The <fstream> Header

Everything you've done with cin and cout so far is stream-based I/O — reading from and writing to the console. C++ extends that exact same idea to files through the <fstream> header, which provides three stream classes:

✍️
std::ofstream
"Output file stream" — for writing data to a file, using << just like cout.
👀
std::ifstream
"Input file stream" — for reading data from a file, using >> or getline() just like cin.
🔁
std::fstream
Combined stream that can both read and write the same file, depending on how it's opened.
📁
Relative paths
A filename with no path, like "notes.txt", is created or read relative to where the program runs.
⚠️
Online compilers vs. your own machine
These examples describe real file I/O exactly as it behaves on a real computer with a real filesystem; if you're following along in a browser-based online compiler rather than a local one, file I/O behavior — and whether files even persist between runs — can vary by platform.

Writing Files with ofstream

Create an ofstream object with the filename you want to write. If the file doesn't exist, it's created; if it exists, its old contents are erased by default. Always check .is_open() before writing — opening a file can fail (permissions, invalid path, disk full).

write_file.cpp
C++
#include <iostream>
#include <fstream>
using namespace std;

int main() {
    ofstream outFile("notes.txt");

    if (!outFile.is_open()) {
        cout << "Failed to open file for writing!\n";
        return 1;
    }

    outFile << "Line 1: Hello, file!\n";
    outFile << "Line 2: C++ file I/O is easy.\n";
    outFile << "Line 3: Written by BitWithBite\n";

    outFile.close();
    cout << "Wrote 3 lines to notes.txt\n";
    return 0;
}
Always close what you open
Calling .close() flushes any buffered data to disk and releases the file handle. In practice an ofstream's destructor closes it automatically when it goes out of scope, but closing explicitly makes your intent clear and lets you check for write errors right away.

Reading Files with ifstream

Open an ifstream the same way. To read whole lines — including spaces — use std::getline(inFile, line) in a loop; it returns false once there's nothing left to read, which makes it a natural while condition. To read space-separated values one token at a time (numbers, single words), use >> instead, exactly like cin >> value.

read_file.cpp — line by line
C++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    ifstream inFile("notes.txt");

    if (!inFile.is_open()) {
        cout << "Failed to open file for reading!\n";
        return 1;
    }

    string line;
    while (getline(inFile, line)) {
        cout << "Read: " << line << "\n";
    }

    inFile.close();
    return 0;
}

Reading word-by-word (or number-by-number)

read_numbers.cpp — token by token
C++
ifstream inFile("numbers.txt");
int value, total = 0;
while (inFile >> value) {   // stops automatically at end of file
    total += value;
}
cout << "Sum: " << total << "\n";

Both loops rely on the same idea: reading from a stream returns the stream itself, and a stream converts to false once it hits end-of-file or an error. That's what lets you write while (getline(inFile, line)) or while (inFile >> value) as a clean loop condition, without manually checking for the end of the file.

Worked Example: Write, Then Read It Back

Here's a single program that writes a short log to a file, then immediately opens the same file again to read and print what was just saved — proving the data really made a round trip through the filesystem.

log_roundtrip.cpp
C++
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    // ── Step 1: write the log ──
    ofstream outFile("log.txt");
    if (!outFile.is_open()) {
        cout << "Could not open file for writing.\n";
        return 1;
    }
    outFile << "Started session\n";
    outFile << "Processed 3 records\n";
    outFile << "Session complete\n";
    outFile.close();

    // ── Step 2: read the log back ──
    ifstream inFile("log.txt");
    if (!inFile.is_open()) {
        cout << "Could not open file for reading.\n";
        return 1;
    }

    string line;
    int lineNum = 1;
    while (getline(inFile, line)) {
        cout << lineNum++ << ": " << line << "\n";
    }
    inFile.close();

    return 0;
}

Output:

Console Output
OUTPUT
1: Started session
2: Processed 3 records
3: Session complete
🎭
Same streams, same mental model
Once you understand cin/cout, file streams cost you almost nothing new to learn — it's the exact same <</>>/getline() vocabulary, just pointed at a file instead of the console.
🧩 Knowledge Check — Lesson 22
Answer all 5 questions to test your understanding. Instant feedback on every answer.
1. Which header do you need for file I/O in C++?
2. Which class do you use to write data to a file?
3. Why should you check .is_open() after opening a file?
4. What does std::getline(inFile, line) do?
5. In while (inFile >> value), what makes the loop stop?
💪
Coding Challenge — Lesson 22
Apply what you learned · Intermediate Level

Now write real file-handling code. Complete the challenge below in your local compiler or IDE.

Challenge: Notes Logger 📝

Write a program that:

1. Opens a file called mynotes.txt for writing and saves at least four lines of "notes" of your choosing (any text you like)
2. Closes the file
3. Re-opens mynotes.txt for reading, and prints every line back to the console, numbered starting from 1
4. Also prints the total number of lines found in the file

Make sure you check .is_open() on both the writing and reading steps, and handle the failure case by printing an error message instead of crashing.
💡 Show hints if you're stuck
  • Reuse the write/read structure from the worked example above
  • Count lines by incrementing a counter inside your while (getline(...)) loop
  • Print the total count after the loop finishes, once the file is fully read
Finished this lesson?
Mark it complete to track your progress.
🎉

Lesson 22 Complete!

You can now save and load real data from disk. Next: the Final Project, where you'll combine classes, STL, exceptions, and file I/O into one complete system.

Module 22 of 26 Phase 5 — Templates & Advanced Concepts