Understanding File Handling in C++, With Examples

Wright Studio / Shutterstock.com

Computers provide us with a lot of ways to handle files and manipulate data. But when you reprogramming, you often want a finer level of control and customization over your files. And when you re working with large amounts ofdata, 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 inC++, 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
Function Overloading in C++
We use specific classes for file operations in C++.

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;
}
Two programmers doing high five hand gesture at desk with multiple screens running code celebrating successful algorithm. Software developers colleagues enjoying teamwork results in it agency
You can manage files directly from your IDE using C++.

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.

example of file handling operations in C++
Simple example of file handling operations in C++, with the expected output.

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.

Leave a Comment