File I/O
File I/O in C++
Since the last lecture primarily focused on references, this studio introduces File I/O in C++ to expand your learning through exploration.
I/O stands for input/output, describing how programs receive and send data to external sources. Throughout the term, you’ve already worked with I/O, as the <iostream> header provides console I/O (e.g., std::cin for input and std::cout for output). File I/O extends this concept to reading and writing data to files, enabled by the <fstream> header.
The <fstream> header introduces two key classes:
std::ifstreamthe input file stream for reading data from files.std::ofstreamthe output file stream for writing data to files.
Both classes are like std::string—they are objects created using constructors. Below, we’ll explore the syntax and examples for using these classes.
Creating File Stream Objects
To create an std::ifstream or std::ofstream object, use the constructor syntax:
<type> <variable_name>(<constructor_arguments>);For example, the following creates an std::ofstream object for writing to a file:
std::ofstream my_cool_ofstream("my_cool_file.txt", std::ios::app);std::ofstream Objects
The std::ofstream constructor accepts:
- A file path (as a
std::string) where data will be written. - An open mode, a constant specifying how the file should be accessed.
Two common modes are:
std::ios::trunc: Truncates (erases) the file’s contents if it already exists, writing new data from scratch.std::ios::app: Appends new data to the end of the file without erasing existing content.
If the file doesn’t exist, it will be created during this process.
Once an std::ofstream object is created, writing to the file is as simple as using the same syntax as std::cout:
std::cout << "Hello, World!" << std::endl; // Writes to the console.hello_world_stream << "Hello, World!" << std::endl; // Writes to the file.Here’s a complete example program that writes “Hello, World!” to a file:
#include <fstream>
int main() { std::ofstream hello_world_stream("hello.txt", std::ios::trunc); hello_world_stream << "Hello, World!" << std::endl;}Execute this program, then check your working directory. A file named hello.txt should appear, containing “Hello, World!”.
std::ifstream Objects
The std::ifstream constructor accepts a single argument: the path to the file to read. The file must already exist and match the expected format. If the file doesn’t exist, the object fails to open.
std::ifstream works similarly to std::cin. For example:
- The stream extraction operator
>>reads data word-by-word. std::getline()reads entire lines.
When created, an std::ifstream object points to the start of the file. As you read data, it moves sequentially through the file.
Consider a file data.txt with the following content:
5George WashingtonJohn AdamsThomas JeffersonJames MadisonJames MonroeHere’s a program that reads this file and prints names in the format: <last name>, <first name>:
#include <iostream>#include <fstream>
int main() { std::ifstream my_cool_data_stream("data.txt");
int num_names; my_cool_data_stream >> num_names;
for (int i = 0; i < num_names; i++) { std::string first_name, last_name; my_cool_data_stream >> first_name >> last_name; std::cout << last_name << ", " << first_name << std::endl; }}If data.txt is present in the working directory, this program will output:
Washington, GeorgeAdams, JohnJefferson, ThomasMadison, JamesMonroe, JamesFinding the Oldest Student
Suppose you have a file, student-data.txt, with the following structure:
<number of students><first name> <last name> <age><first name> <last name> <age>...Write a program to:
- Read data from
student-data.txtto identify the oldest student. - Write the oldest student’s name and age to a new file,
oldest-student.txt, with each detail on a separate line.
In other words:
- Create an
std::ifstreamobject forstudent-data.txt. - Use the stream extraction operator to read the data and determine the oldest student.
- Create an
std::ofstreamobject foroldest-student.txtin truncate mode. - Write the oldest student’s details (first name, last name, age) to the file.
You can either use the stream extraction operator >> or std::getline() to read from a std::ifstream object, just as you can with std::cin. However, recall that you should avoid mixing both of these mechanisms on a single stream in a single program, unless you’re very careful about how you handle whitespace. For this particular program, it’s strongly recommended that you stick with the stream extraction operator.