C, C++, MFC  

Chapter 18: File I/O and Stream Operations in C++

Previous chapter: Chapter 17: Exception Handling: Robust Error Management in C++

Nearly every non-trivial application needs to persist data. This chapter covers File Input/Output (I/O) in C++ using the standard stream library (<fstream>), allowing programs to read data from disk files and write results back.

1. The C++ Stream Hierarchy

C++ manages I/O through a hierarchy of classes, all derived from std::ios:

  • std::ostream (Output Stream): Used for writing data (e.g., std::cout).

  • std::istream (Input Stream): Used for reading data (e.g., std::cin).

  • std::fstream (File Stream): The core header for file operations.

2. Writing Data to a File (std::ofstream)

The output file stream (std::ofstream) is used to write data to a file. It inherits the stream insertion operator (<<) from std::ostream.

#include <fstream>
#include <iostream>

void write_to_file(const std::string& filename) {
    // 1. Create an ofstream object
    std::ofstream output_file(filename);

    // 2. Check if the file was successfully opened
    if (output_file.is_open()) {
        output_file << "This is the first line of C++ data." << std::endl;
        output_file << 12345 << std::endl;
        output_file.close(); // 3. Close the file when finished
        std::cout << "Data written successfully." << std::endl;
    } else {
        std::cerr << "Unable to open file: " << filename << std::endl;
    }
}

File Modes: You can specify file opening modes (e.g., std::ios::app for appending data) as a second argument to the constructor.

3. Reading Data from a File (std::ifstream)

The input file stream (std::ifstream) is used to read data from a file. It inherits the stream extraction operator (>>) from std::istream.

#include <fstream>
#include <string>

void read_from_file(const std::string& filename) {
    std::ifstream input_file(filename);
    std::string line;

    if (input_file.is_open()) {
        // Read the file line by line
        while (std::getline(input_file, line)) {
            std::cout << "Read: " << line << std::endl;
        }
        input_file.close();
    } else {
        std::cerr << "Unable to open file for reading." << std::endl;
    }
}

4. Checking Stream Status

It's vital to check the state of a stream after an I/O operation to determine success or failure.

State FlagDescription
.good()Returns true if no errors have occurred.
.fail()Returns true if a reading error or formatting failure occurred.
.eof()Returns true if the end-of-file has been reached.
.bad()Returns true if a non-recoverable I/O error occurred.

A standard loop condition like while (input_file >> value) implicitly checks if the stream is in a good state, making it a clean way to read successive data items.