Key Points
- File handling in C++ involves managing, creating, reading, and writing files using the programming language.
- The main classes used for file handling in C++ are ifstream, ofstream, and fstream.
- File handling operations in C++ include writing formatted data, checking stream state, setting precision and width, reading lines of text, and opening and closing files.
- An example code block demonstrates how to open, write to, and read from a file in C++.
- Understanding file handling in C++ allows for efficient file manipulation and integration with other systems.
Computers provide us with a lot of ways to handle files and manipulate data. But when you’re programming, you often want a finer level of control and customization over your files. And when you’re working with large amounts of data, some programs can introduce unnecessary overheads and impair performance. These are situations where you may need a more robust technique, especially if you’re developing a program. In this article, we’re going to explore the elements involved in file handling in C++, including the operations used and best practices.
What Is File Handling in C++?
You may guess that file handling refers to the process involved in managing, creating, reading, and writing files, and you’d be absolutely right. As such, file handling in C++ is where we use the programming language to manipulate our files of data. This is usually preferable when developing a C++ project and vast amounts of data, as we can work quickly in the same language we’re developing in. C++ provides us with a lot of classes that can be used for handling files. We’ll get into the basics behind these next.
Classes for File Handling
The main classes used for handling files in C++ are ifstream, ofstream, and fstream. Usually, when we’re working with C++, we import the iostream header file, as this is needed for all standard input/output operations. However, when we want to manage files, we go one step further and import the fstream class as well. This provides us with specific classes to manipulate files effectively. We’ve summarized the class hierarchy and class functions in the following table:
Class | Function | Derived from | Extends to | Operations |
---|---|---|---|---|
iostream | Header file, provides basic input/output operations | None | None | << and >> operators, tie(), flush() |
ios | Base class, provides functionality for istream and ostream | None | istream, ostream | good(), bad(), fail(), clear(), setstate(), precision(), width() |
istream | Base class for input stream, used for reading files | iostream | None | getline(), ignore(), peek(), get(), open(), close() |
ostream | Base class for output stream, used for writing files | iostream | None | put(), write(), open(), close() |
fstreambase | Base class, with functionality for file streams specifically, i.e. opening and closing and error handling | iostream | ifstream, ofstream, fstream | None |
ifstream | Used to read data from files. Typically inherits istream and adds specific functionality | fstreambase | None | Same as istream, but has opening functionality as well |
ofstream | Used for writing data to files. Inherits from ostream and adds specific functionality | fstreambase | None | Same as ostream, but has opening functionality as well |
fstream | Used for reading and writing data to files. Inherits from istream and ostream, and adds specific functionality | fstreambase | None | Same as istream and ostream, but has opening functionality as well |
streambuf | Interface for handling stream buffers, i.e. managing data storage and transfer. | ios | None | sputc(), sgetc(), sputn(), sgetn() |
filebuf | Interface between file and stream buffers. | ios | None | Same as streambuf, but has opening and closing functionality as well |

©Monstar Studio/Shutterstock.com
File Handling Operations
There’s a brief overview of the operations involved in the previous table, but the following provides some more detail on how these work.
Operation | Use |
---|---|
<< | Overloaded operator, writes formatted data to an output stream. |
>> | Overloaded operator, reads formatted data from an input stream. |
tie() | Gets or sets the tied stream object, i.e. an input or output stream that’s synchronized with another stream. |
flush() | Flushes an output sequence, meaning the data is written immediately to the output destination. |
good() | Checks if stream state is good, and returns true if so. |
bad() | Checks if stream state is bad, and returns true if so. |
fail() | Checks if a failure has occurred, and returns true if so. |
clear() | Clears error flags and resets stream state. |
setstate() | Manually sets error flags. |
precision() | Sets number of decimal digits to display in an output. |
width() | Sets field width for output, i.e. the minimum number of characters to be written. |
getline() | Reads a line of text from an input stream until it reaches a newline. |
ignore() | Ignores a specific number of characters from an input stream. |
peek() | Returns next character of input stream without removing it. |
get() | Extracts single character from an input stream and increments the stream position. |
open() | Opens a file for reading or writing. |
close() | Closes a file. |
put() | Writes a character to the output stream. |
write() | Writes a block of data to the output stream, usually a specified number of characters. |
sputc() | Writes a single character to the output buffer. |
sgetc() | Reads a single character from the input buffer. |
sputn() | Writes a block of characters to the output buffer, using a pointer to the buffer and a specified number of characters. |
sgetn() | Reads a block of characters from the input buffer, using a pointer to the buffer and specified number of characters. |
Example of Operations
Now that we’ve gone over the basic operations and classes involved in file handling, let’s illustrate some of them with an example. Consider this code block:
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ofstream file("data.txt");
if (file.is_open()) {
std::string message = "Hello, World!";
int number = 42;
file.precision(2);
file.width(10);
file.tie(&std::cout);
file << "Message: " << message << std::endl;
file << "Number: " << number << std::endl;
file.flush();
if (file.good()) {
std::cout << "File write operation was successful." << std::endl;
} else {
std::cout << "File write operation failed." << std::endl;
}
file.close();
} else {
std::cout << "Failed to open the file." << std::endl;
return 1;
}
std::ifstream inputFile("data.txt");
if (inputFile.is_open()) {
char character;
std::string line;
character = inputFile.get();
std::cout << "Character: " << character << std::endl;
inputFile.clear();
inputFile.ignore(4);
character = inputFile.get();
std::cout << "Next Character: " << character << std::endl;
inputFile.seekg(0);
character = inputFile.peek();
std::cout << "Peeked Character: " << character << std::endl;
inputFile.ignore(std::numeric_limits<std::streamsize>::max(), 'n');
std::getline(inputFile, line);
std::cout << "Line: " << line << std::endl;
inputFile.close();
} else {
std::cout << "Failed to open the file for reading." << std::endl;
return 1;
}
return 0;
}

©DC Studio/Shutterstock.com
Explanation of Code
First, we import the necessary modules — “iostream” for input/output operations, “fstream” for file operations, and “string” for manipulating strings.
Opening the File, and Declaring Variables
Next, we declare the “main()” method, which declares an object called “file”, and opens a truncated file called “data.txt” in write mode. We then check if the file was opened successfully using “is_open()”.
After this, we declare the “message” string variable, assigning the “Hello, World!” value to it, and the “number” integer variable, assigning the value of 42. We also set the decimal values to 2 using “precision()” and the width to 10 using “width()”.
“tie()” is then used to synchronize the “file” stream with the “std::cout” stream, meaning that when we write to “file”, we also write to “std::cout”.
Writing the Message
The “<<” is used after that to write the message and number to the file. The output buffer is then flushed to make sure the data is written.
A check is then performed to make sure the state of the file is good and the operation was finished successfully. The message is also printed to indicate this, and the file is closed.
We then declare a new object of the “std::fstream” stream, called “inputFile”. We also open this file in read mode. The opening of the file is checked. The “character” and “line” variables are also declared.
Reading and Printing
“get()” is used to read a single character from the file, which is stored in the character variable and printed. Any potential error flags are also cleared using the “clear()” method.
The next 4 characters are ignored using “ignore()”, and then the next character is printed using “get()”.
After this, the position is moved to the beginning of the file with “seekg()” and the next character is printed using “peek()”. All remaining characters are then ignored until a newline is reached, and “getline()” is used to read the entire line, which is stored in the line variable and printed.
Lastly, the file is closed. The output can be seen in the accompanying image.

©History-Computer.com
Wrapping Up
There are many operations involved with file handling in C++. By understanding these, you can read and write files efficiently, as well as process files line by line and store data persistently. It’s important to check the file state and return error codes to handle any issues that arise effectively. Gaining an appreciation for file handling will also help you integrate your data with other systems, making it more robust.
The image featured at the top of this post is ©Wright Studio/Shutterstock.com.