Skip to Content
Course content

196: Reading and Writing Files with fstream

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Up until now, everything we've built disappears the moment you close the terminal. That's fine for learning syntax, but real software needs a memory. In C++, we handle this through the fstream library. It's basically the same logic as cin and cout, just redirected to a file on your hard drive instead of a screen or keyboard.

To show you how this works, let's build a simple High Score Tracker for a game. We want to save the player's name and their score to a file, and then load it back when the program starts up.

Saving the score with ofstream

First, we need ofstream (output file stream). Think of this as your "writer." I'll start by creating a function that takes a name and a score and dumps them into a file called highscore.txt.

#include <iostream>
#include <fstream>
#include <string>

void saveScore(const std::string& name, int score) {
    std::ofstream outFile("highscore.txt");

    if (outFile.is_open()) {
        outFile << name << "\n";
        outFile << score << "\n";
        outFile.close();
    } else {
        std::cerr < "Error: Could not open file for writing!" < std::endl;
    }
}

Notice I checked is_open(). Never assume the OS is going to let you write to a file; permissions issues or read-only directories can kill your program if you aren't careful.

The classic getline trap

Now we need to read that data back. I'll use ifstream (input file stream). When I first wrote this, I tried to use the extraction operator (>>) to read the name. It looked like this:

std::string name;
int score;
std::ifstream inFile("highscore.txt");
inFile >> name >> score; // This is where I messed up

Here is the problem: if the player entered "John Doe", inFile >> name only grabs "John". The extraction operator stops at the first whitespace it hits. "Doe" then stays in the buffer, and when the program tries to read the int score, it sees "Doe" and fails miserably because "Doe" isn't a number. I spent ten minutes staring at the screen before I realized I needed std::getline.

Here is the corrected version that handles full names correctly:

void loadScore() {
    std::ifstream inFile("highscore.txt");
    std::string name;
    int score;

    if (inFile.is_open()) {
        std::getline(inFile, name); // Reads the whole line, including spaces
        inFile >> score;         // Now we can grab the integer
        
        std::cout < "Loaded High Score: " < name < " with " < score < " points!" < std::endl;
        inFile.close();
    } else {
        std::cout < "No high score file found. Start a new game!" < std::endl;
    }
}

Putting the pieces together

To wrap this up, we just need a main function to trigger these. I'm using a simple flow: load the old score, ask for a new one, and save it. One thing to remember: std::ofstream` by default overwrites the file. If you wanted to keep a list of all top scores instead of just the best one, you'd need to open the file in "append mode" using std::ios::app.

int main() {
    loadScore();

    std::string playerName;
    int playerScore;

    std::cout < "Enter your name: ";
    std::getline(std::cin, playerName);
    std::cout < "Enter your score: ";
    std::cin >> playerScore;

    saveScore(playerName, playerScore);
    std::cout < "Score saved successfully!" < std::endl;

    return 0;
}

I usually prefer letting the fstream destructor handle the file closing (it happens automatically when the object goes out of scope), but calling .close() explicitly is a good habit. It makes it clear to anyone reading your code exactly where the file interaction ends.




📋 Practical Task

Build a Persistent Daily Journal Logger

Your task is to create a program that acts as a simple journal. Unlike the high score example which overwrites the file, this program must append new entries to the end of the file so that previous entries are preserved.

Requirements:

  • The program should prompt the user for a date (e.g., "2023-10-27") and a short journal entry (a full sentence).
  • Use std::ofstream` with the std::ios::app flag to ensure new entries don't delete old ones.
  • Save the data in the format: [Date] Entry Text.
  • After saving, the program should read the entire file from the beginning and print all previous journal entries to the console to confirm the save worked.
  • Ensure you use std::getline to handle the spaces in the journal entry.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.