C++ Files and Streams
C++ Files and Streams
Section titled “C++ Files and Streams”So far, we have used the <iostream> standard library, which provides std::cin and std::cout for reading from standard input and writing to standard output. To work with files, C++ provides the <fstream> library.
The <fstream> library defines three main data types for file I/O:
| Data Type | Description |
|---|---|
std::ofstream | Output File Stream: Used to create files and write data to files. |
std::ifstream | Input File Stream: Used to read data from files. |
std::fstream | File Stream: Combines ofstream and ifstream capabilities for both reading and writing. |
To perform file processing in C++, you must include the <fstream> header file. It’s also common to include <iostream> for console interaction and <string> for handling text.
Opening a File (Modern Approach)
Section titled “Opening a File (Modern Approach)”In modern C++, the easiest way to open a file is during the stream object’s construction. This uses the RAII (Resource Acquisition Is Initialization) principle, meaning the file is automatically closed when the stream object goes out of scope (e.g., at the end of a function).
std::ofstream outputFile("mydata.txt"); // Opens for writing (truncates if exists)std::ifstream inputFile("mydata.txt"); // Opens for readingstd::fstream ioFile("mydata.txt", std::ios::in | std::ios::out); // Opens for read/writeYou should always check if the file was opened successfully:
std::ofstream outputFile("mydata.txt");if (!outputFile) { // Or !outputFile.is_open() std::cerr << "Error opening file for writing!" << std::endl; // Handle error, maybe return or exit}Opening with open() and Modes:
Section titled “Opening with open() and Modes:”Alternatively, you can create the stream object first and then call the open() member function. The second argument specifies the mode:
void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out); // ofstream defaultvoid open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in); // ifstream defaultCommon file modes (defined in std::ios_base):
| Mode Flag | Description |
|---|---|
std::ios::app | Append to the end of the file. |
std::ios::ate | Seek to the end of the file upon opening. |
std::ios::binary | Open in binary mode (rather than text mode). |
std::ios::in | Open for reading (default for ifstream). |
std::ios::out | Open for writing (default for ofstream). |
std::ios::trunc | Truncate file to zero length if it exists (default for ofstream when not using app or in). |
Combine modes using the bitwise OR operator (|). For example, to open for output in binary mode, appending if the file exists:
std::ofstream outfile;outfile.open("data.bin", std::ios::out | std::ios::binary | std::ios::app);Closing a File:
Section titled “Closing a File:”If you use the RAII approach (opening in the constructor), the file is closed automatically when the stream object is destroyed. This is the preferred method as it’s less error-prone.
If you used the open() method, you can explicitly close the file using close(). However, relying on RAII is generally better.
// Only needed if RAII wasn't used or if you need to check close statusif (outfile.is_open()) { outfile.close();}Writing to a File:
Section titled “Writing to a File:”Use the stream insertion operator (<<) with an ofstream or fstream object, just like you use std::cout:
std::ofstream outputFile("greeting.txt");if (outputFile) { std::string name = "Alice"; int age = 30; outputFile << "Hello, " << name << "!\n"; outputFile << "Your age is: " << age << std::endl;} // File automatically closed hereReading from a File:
Section titled “Reading from a File:”Use the stream extraction operator (>>) with an ifstream or fstream object, similar to std::cin. To read line by line, use std::getline().
// Reading whitespace-separated valuesstd::ifstream inputFile("data.txt");int value1;double value2;std::string word;if (inputFile) { inputFile >> value1 >> value2 >> word; // Check if reads were successful: if (!inputFile) { handle error... }}
// Reading line by linestd::ifstream textFile("document.txt");std::string line;if (textFile) { while (std::getline(textFile, line)) { // Reads until newline or EOF std::cout << "Read line: " << line << std::endl; }} // File automatically closed hereImportant Note: Mixing >> and std::getline() requires care, as >> often leaves the newline character in the stream, which std::getline() might then read as an empty line. You might need inputFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); after using >> and before std::getline().
Read & Write Example (Modernized):
Section titled “Read & Write Example (Modernized):”This program asks the user for their name and age, writes them to user_data.txt, then reads the data back and displays it.
#include <fstream>#include <iostream>#include <string>#include <limits> // Required for numeric_limits
int main() { std::string name; int age; const std::string filename = "user_data.txt";
// --- Writing to the file --- { std::ofstream outfile(filename); // Opens for writing (RAII style) if (!outfile) { std::cerr << "Error opening " << filename << " for writing." << std::endl; return 1; }
std::cout << "Writing to the file " << filename << std::endl; std::cout << "Enter your name: "; std::getline(std::cin, name); // Read full name with spaces
std::cout << "Enter your age: "; std::cin >> age;
// Ignore the newline character left by std::cin >> age std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Write data to the file outfile << name << std::endl; // Write name on its own line outfile << age << std::endl; // Write age on its own line
std::cout << "Data written successfully." << std::endl; // outfile is automatically closed when it goes out of scope here }
std::cout << "\nReading from the file " << filename << std::endl;
// --- Reading from the file --- { std::ifstream infile(filename); // Opens for reading (RAII style) if (!infile) { std::cerr << "Error opening " << filename << " for reading." << std::endl; return 1; }
std::string read_name; int read_age;
// Read data from the file if (std::getline(infile, read_name) && (infile >> read_age)) { // Display the data std::cout << "Name read: " << read_name << std::endl; std::cout << "Age read: " << read_age << std::endl; } else { std::cerr << "Error reading data from the file." << std::endl; } // infile is automatically closed when it goes out of scope here }
return 0;}Sample interaction:
Writing to the file user_data.txtEnter your name: Ada LovelaceEnter your age: 36Data written successfully.
Reading from the file user_data.txtName read: Ada LovelaceAge read: 36File Position Pointers:
Section titled “File Position Pointers:”Both input (istream) and output (ostream) streams maintain a position indicator specifying the next read/write location. You can manipulate these using seekg (seek get) for input streams and seekp (seek put) for output streams.
The functions typically take an offset (usually std::streamoff, a type like long long) and an optional direction (std::ios_base::seekdir):
std::ios::beg: Offset relative to the beginning of the stream (default).std::ios::cur: Offset relative to the current position.std::ios::end: Offset relative to the end of the stream.
Example usage for an input stream fileObject:
// Position to the 10th byte from the beginningfileObject.seekg(10, std::ios::beg); // or fileObject.seekg(10);
// Move 5 bytes forward from the current positionfileObject.seekg(5, std::ios::cur);
// Position 8 bytes back from the endfileObject.seekg(-8, std::ios::end);
// Position at the end of the filefileObject.seekg(0, std::ios::end);
// Get current positionstd::streampos currentPos = fileObject.tellg();seekp and tellp are the corresponding functions for output streams (ostream). Be cautious when using seeking in text mode, as the interpretation of offsets might be system-dependent due to newline character translations. Seeking is more reliable in binary mode (std::ios::binary).
For more advanced file system operations like creating directories, checking file existence, or iterating through directory contents, consider using the C++17 <filesystem> library.