File Handling in C++
Learn via video course

Overview
A file is a basic entity that stores the user's relevant data. The concept of file I/O in programming refers to reading and writing files stored in a secondary storage device through a program. The C++ programming language provides several classes for file I/O operations, including ofstream, ifstream, and fstream.
Scope
- This article will discuss the file input-output classes in c++.
- Subsequently, we will do file handling in a C++ program, like opening a file, reading a file, and writing to a file with those classes.
- Before coming to an end, we will discuss related concepts like file position pointer, stream flush, etc.
File Input/Output Classes In C++
Before understanding file I/O, let's discuss some basic concepts of programming,
A program is a set of instructions that manipulates some data according to the specified algorithm. The data is then used for several purposes.
Whenever we execute a program, it gets loaded into the main memory, and all data required for the program also exists in the main memory. But in real-world programming, manipulation exists on a large data set (typically in GigaBytes), so we will not store all data on Main Memory. The extensive data remains stored on disk, and through a stream, we bring only a particular set of data that the program needs now.
What is File Handling in C++?
The basic entity that stores the user's relevant data is called a file. Files can have a lot of types that are depicted by their extensions. For example : .txt(text file), .cpp(c++ source file), .exe(executable file), .pdf(portable document file) and many more.
File Handling stands for the manipulation of files storing relevant data using a programming language, which is C++ in our case. This enables us to store the data in permanent storage even after the program performs file handling for the same ends of its execution. C++ offers the library fstream for file handling. Here we will discuss the classes through which we can perform I/O operations on files. For taking input from the keyboard and printing something on the console, you might have been using the cin(character input stream) and cout(character output stream) of the istream and ostream classes. File streams are similar to them. Only the console here is replaced by a file.
Below are three stream classes of the fstream library for file handling in C++ that are generally used for file handling in C++.
ofstream
The ofstream is derived from the ostream class. It provides the output stream to operate on file. The output stream objects can be used to write the sequences of characters to a file. This class is declared in the fstream header file.
ifstream
The ifstream is derived from the istream class. It provides the input stream to operate on file. We can use that input stream to read from the file. This class is declared in the fstream header file.
fstream
The fstream is derived from the iostream class, and the iostream is further derived from the istream and ostream classes. It provides the input as well as output streams to operate on file. If our stream object belongs to the fstream class, we can perform read and write operations on the file with the same stream object. This class is declared in the fstream header file.
Opening a File
To start working with the file, first, we need to open it in our program. We can either open our file with the constructor provided by the file I/O classes or call the open method on the stream object. Before discussing how the file can be opened, it is necessary to discuss several opening modes.
Opening Modes
There are several modes we can specify when opening a file. These modes correspond to various controls given to stream objects during file handling in c++. The opening mode's description and syntax are in the tabular form below.
Mode | Syntax | Description |
---|---|---|
Read | ios::in | Opens file for reading purpose. |
Write | ios::out | Opens a file for writing purposes. |
Binary | ios::binary | All operations will be performed in binary mode. |
Truncate before Open | ios::trunc | If the file already exists, all content will be removed immediately. |
Append | ios::app | All provided data will be appended in the associated file. |
At End | ios::ate | It opens the file and moves the read/write control at the End of the File. The basic difference between the ios::app and this one is that the former will always start writing from the end, but we can seek any particular position with this one. |
1. Open a File Using Constructor
Each class has two types of constructors: default and those that specify the opening mode and the associated file for that stream.
2. Open a File Using stream.open() Method
The open() is a public member function of all these classes. Its syntax is shown below.
The open() method takes two arguments: the file name and the mode in which the file will open.
The is_open() method is used to check whether the stream is associated with a file. It returns true if the stream is associated with some file; otherwise returns false.
Reading from a File
We read the data of a file stored on the disk through a stream. The following steps must be followed before reading a file,
- Create a file stream object capable of reading a file, such as an object of ifstream or fstream class.
- Open a file through the constructor while creating a stream object or calling the open method with a stream object.
- Check whether the file has been successfully opened using is_open(). If yes, then start reading.
1. Using get() Method
Output:
Explanation:
- First, we have created a stream object of the ifstream class and are providing the file name to open it in reading mode(default).
- Next, we check whether the file is being opened successfully. If yes, we read one character at a time until the file is good.
- The good() function returns true if the end of the file is not reached and there is no failure.
2. Using getline() Method
Output:
Explanation:
- At the beginning of the program, we opened the file with the constructor of the ifstream class.
- If the file is successfully opened, the 'open' function will return true, and the if block will be executed.
- In the while loop, we check whether the file stream is good for operations. When the end of the file is reached, the good function will return false.
- We have declared a string to store each line of file through the getline function, and later we are printing that string.
Writing to a File
In writing, we access a file on disk through the output stream and then provide some sequence of characters to be written in the file. The steps listed below need to be followed in writing a file,
- Create a file stream object capable of writing a file, such as an object of ofstream or fstream class.
- Open a file through the constructor while creating a stream object or calling the open method with a stream object.
- Check whether the file has been successfully opened. If yes, then start writing.
1. Writing in Normal Write Mode
Output:
Explanation:
- << operator is used for writing on the file.
- The text given above will be shown in our sample.txt after running the program.
2. Writing in Append Mode
Output:
Explanation:
- The same sample.txt, which was used in the last example, has more content appended to it now.
3. Writing in Truncate Mode
Output:
Explanation:
- Again, we use the same sample.txt file from the previous Example. Now all older content is being removed.
Closing a File
The concept of closing a file during file handling in c++ refers to the process of detaching a stream with the associated file on disk. The file must be closed after performing the required operations on it. Here are some reasons why it is necessary to close the file,
- The data might be in the buffer after the write operation, so closing a file will cause the data to be written in the file immediately.
- When you need to use the same stream with another file, it is a good practice to close the previous file.
- To free the resources held by the file.
When the object passes out of scope or is deleted, the stream destructor closes the file implicitly.
File Position Pointers
A file position pointer points to a particular index in a file where read or write operations occur.
There are two types of pointers get and put. We can find the position of these pointers by associated functions tellg() and tellp().
Also, we can seek(change) the position of the pointer with the function seekg() and seekp(). There, we can either read or write after seeking a particular position.
Methods like seekg(), seekp() takes parameters as long integers and seek directions.
A few examples are :
ios::beg (for positioning at the beginning of a stream)
ios::cur (for positioning relative to the current position of a stream)
ios::end (to position relative to the end of a stream)
tellp() & tellg()
tellp() returns the current position of put pointer, which is used with output streams while writing the data to the file.
tellg() returns the current position of get pointer, which is used with input streams while receiving the data from the file.
Example:
Output:
Explanation:
- Before writing anything to the file, it was opened in the out mode; hence the put pointer was at .
- After writing the string Hello Everyone, the put pointer will reach to end of the file, which is .
- For reading, the get pointer is used, and the initial position of the get pointer is .
- After reading five characters from the file, the get pointer reaches .
seekg() & seekp()
- istream& seekg (streampos pos), this function returns the istream object by changing the position of get pointer to pos.
- istream& seekp (streampos pos), this function returns the ostream object by changing the position of put pointer.
- We could also overload the seekg() & seekp() by providing an offset. Pointers will move with respect to offsets, i.e., ios_base::beg to start from the beginning of the file, ios_base::end to start from the ending of the file, ios_base::curr to start from the current positions of the pointer.
- The default value of offset is the beginning of the file.
Example:
Output:
Explanation:
- Initially, we have written a string into a file named myfile.txt.
- Later, we have to change the position of the put pointer to the 5th index using seekp() and then write "*" to the file, which will overwrite to file.
- Then, for the reading operation, we change the get pointer position to the 3rd index, which means reading will start from that position.
- As we can see from the output, the string started from the 3rd index, and the 5th index is changed to '*'.
Checking State Flags
The state flags of the file tell about the current state of the file, and there are several functions to retrieve the current state.
- eof(), This function returns true if the end of the file is reached while reading the file.
- fail() returns true when the read/write operation fails or a format error occurs.
- bad() returns true if reading from or writing to a file fails.
- good() checks the state of the current stream and returns true if the stream is good for working and hasn't raised any error. good() returns false if any of the above state flags return true; otherwise, it returns true.
Flushing a Stream
In C++, the streams get buffered by default for performance reasons, so we might not immediately get the expected change in the file during a write operation. To force all buffered writes to be pushed into the file, we can either use the flush() function or std::flush manipulator.
Conclusion
- The file I/O in programming means interacting with the file on the disk to receive and provide the data.
- File Handling is the manipulation of files storing relevant data using a programming language( i.e., C++ in our case).
- We have three different classes: ifstream, ofstream, and fstream. These all are declared in the fstream header and provide us stream through which we can access the file and subsequently perform file handling in C++.
- To start working with a file, first, we have to open that file. We can do this either during the construction of the stream object or by calling the open() method on the stream object.
- There could be several modes of file opening we can choose according to our requirements.
- After working on the file, it is a good practice to close it with the help of the close() method of stream object.