CppFile I/O (fstream)

File I/O (fstream)

So far, input and output have meant the console — cin and cout. Reading and writing files works almost identically, thanks to the <fstream> header, which provides file-based stream classes that plug into the same << and >> operators you already know.
The three stream types

Class

Purpose

std::ifstream

Input file stream — for reading from a file.

std::ofstream

Output file stream — for writing to a file.

std::fstream

Combined stream that can both read and write the same file.

Writing to a file

write-file.cpp

CPP
#include <fstream>
#include <iostream>

int main() {
  std::ofstream outFile("scores.txt");

  if (!outFile) {
    std::cerr << "Could not open scores.txt for writing.\n";
    return 1;
  }

  outFile << "Alice 92\n";
  outFile << "Bob 85\n";
  outFile << "Carol 78\n";

  // outFile closes automatically when it goes out of scope.
  return 0;
}
Checking that the file actually opened
Always check if (!file) before using a stream
Opening a file can fail silently — a typo in the path, missing permissions, or a full disk won't throw by default. If you skip the check, every read or write on a failed stream just quietly does nothing (or returns garbage), and the bug shows up far from its cause. A stream converts to a boolean that is false when it's in a failed state, so if (!file) is all you need.
Reading a file line by line
The most common way to read a text file is a loop around std::getline(), which reads one line at a time into a std::string and returns the stream itself — which is falsy once there's nothing left to read, making it a natural loop condition.

read-file.cpp

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

int main() {
  std::ifstream inFile("scores.txt");

  if (!inFile) {
    std::cerr << "Could not open scores.txt for reading.\n";
    return 1;
  }

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

  return 0;
}
You can also read formatted values directly with >>, just like with cin:

read-formatted.cpp

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

int main() {
  std::ifstream inFile("scores.txt");
  std::string name;
  int score;

  while (inFile >> name >> score) {
    std::cout << name << " scored " << score << "\n";
  }
  return 0;
}
RAII closes the file for you
Notice none of the examples above call close() explicitly. File stream objects follow the same RAII pattern used throughout the standard library: the destructor closes the underlying file automatically when the stream object goes out of scope, whether the function returns normally or an exception unwinds the stack. You can call .close() manually if you need the file released before the end of scope, but it's rarely required.
See also: RAII
This is the same resource-management idea covered on the RAII page — a stream object "acquires" the open file handle in its constructor and releases it in its destructor, so you can't forget to close it.
File modes

The second argument to a stream's constructor is a set of flags controlling how the file is opened. A few are especially common:

  • std::ios::app — append writes to the end of the file instead of overwriting it.

  • std::ios::binary — open in binary mode, writing/reading raw bytes without any text translation.

  • std::ios::trunc — truncate (clear) an existing file before writing (the default for ofstream).

  • Flags can be combined with the bitwise OR operator, e.g. std::ios::out | std::ios::app.

append-mode.cpp

CPP
#include <fstream>

int main() {
  std::ofstream logFile("app.log", std::ios::app);
  logFile << "Application started\n";
  return 0;
}