Understanding Read Write And Append File Operations in C++

Discussion in 'C++' started by usmanmalik, Jan 12, 2014.

  1. usmanmalik

    usmanmalik New Member

    Joined:
    Dec 28, 2013
    Messages:
    19
    Likes Received:
    14
    Trophy Points:
    0
    Programs you code reside in random access memory or commonly known as RAM. RAM is also known as volatile memory space. What happens is that when you run a program, your CPU selects corresponding files to execute from your hard drive and loads it into memory. A problem here arises that the data of the program remains in the memory for the time program itself remains in the memory. Once we close the program the data of the program also get vanished and there is no way to retrieve.

    Why File Handling?



    For learning purpose we do not need to store our data permanently to any file but in real world this is not the case. Suppose you have developed a calculator program; you add two numbers and display the result on the screen. The result remains on the screen until close the window, once you close the output window, the result will be vanished from the memory. You close the calculator program and carry on with your work. What if at some later point of time you need the result of your mathematical calculation you performed earlier. You can never retrieve the value.

    You can directly skip to
    1. Writing Data to a File
    2. Appending Data to an Existing File
    3. Reading Data from File
    File handling allows you to store the data of your program on your file on the hard drive so that you can retrieve it later on. Apart from writing data on your files, you often need to read data from files and process the data. A typical example of such systems is ticket reservation systems. These systems use large databases instead of file but basic concept is the same. You need mechanism to store and retrieve data into files which can be read later on. This mechanism is basically called file handling in C++ and in this tutorial; I am going to give you the basic overview of how it is done and where it is used. We will see how we can access files from our programs and can perform several tasks like, reading writing to these files.

    Classes for Reading/Writing Files



    In C++, three major files are used for interacting with files.

    1. fstream

    ifstream (Input Stream) is a class that is used to obtain input from any file. This class extracts the contents from the file. In simplest words, we can say that in order to read data from a file we use ifstream class.

    2. ofstream

    ofstream (Output Stream) class performs functions opposite to that of ifstream class. It is used to create a file and insert content into the file. In simpler words, this class is used to write data to a file.

    3. fstream

    This is a generic base class and can be used for both reading and writing data to the file.

    Writing Data to a File



    To understand how can we write data to a file, consider Example1.

    Example1
    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main()
    {
        ofstream OFileObject;  // Create Object of Ofstream
        OFileObject.open ("D:\\ExampleFile.txt"); // Opening a File or creating if not present
        OFileObject << "I am writing to a file opened from program.\n"; // Writing data to file 
        cout<<"Data has been written to file";
        OFileObject.close(); // Closing the file
    }
    
    Pay attention to the code snippet in Example1. You can see that in the header files section. We have added <fstream> library. It means that inside the body of the main function we can perform both file reading and file writing tasks. If we wanted to perform only writing tasks we needed ofstream library. Similarly, if we wanted to perform only reading tasks we require ifstream.

    Now come inside the main function. In the first line inside the main function we created the object of ofstream class. We named it OFileObject. Now in order to interact with the file we will use this object in rest of the program.

    In the next line, we called the ‘open’ of the ofstream class using OFileObject. We passed the path where the file is present and the name of the file to which we want to write the content.
    Code:
    OFileObject.open ("D:\\ExampleFile.txt");
    In this line we are asking our OFFileObject to open the file named “ExampleFile.txt” which is located in the root Directory ‘D’.

    The next line is the most fascinating part of the stream classes. In order to write content to the file you can simply use insertion operator as you used with the cout and cin.
    Code:
    OFileObject << "I am writing to a file opened from program.\n";
    You can see that in the above line of code we have simply appended insertion in front of the OFFileObject followed by a string. This string will be written to our file ExampleFile.txt, located in the directory D. Execute the code in Example1 and go to your directory D and check there should be a text file named ExampleFile and it should contain the string ‘I am writing to a file opened from program’

    Now, you must be thinking what if there already is a file with same name in the same directory where we want to create a new file with same name. The answer is that in case a file with same name and type is present in the directory our program will overwrite it.

    Appending Data to an Existing File



    What if you do not want to over write the existing file in the directory? Instead you want that whatever you write should be appended at the end of the existing file without creating a new file with the same name. C++ also provides mechanism for that.

    In Example1 we only provided one parameter to the open function of the ofstream class’s object. However this method has another overload. Look at the following definition of open method.
    Code:
    open(file name, mode)
    Here we have additional parameter named mode. This mode actually specifies that why are we opening the file or for what purpose we want to open the file. We can pass several arguments to the mode parameter which we will discuss later however in this section we will explain with the help of example that how you can append data to the existing file using this mode parameter. Have a look at Example2 for this purpose.

    Example2
    Code:
    #include <iostream>
    #include <string>
    #include <fstream>
    using namespace std;
    
    int main()
    {
        ofstream OFileObject;  // Create Object of Ofstream
        OFileObject.open ("D:\\ExampleFile.txt", ios::app); // Append mode
        OFileObject << "I am writing to a file opened from program.\n"; // Writing data to file
        cout<<"Data has been appended to file";
        OFileObject.close(); // Closing the file
    }
    
    In Example2, everything is same as Example1. But look at the open function which is being called by the OFileObject. Here we have passed one additional argument ‘ios::app’. This mode parameter will tell the compiler that you do not need to overwrite the existing file, instead you should append the data at the end of the file contents. If you execute the above program thrice, the string ‘I am writing to a file opened from program’ will be appended thrice to the end of the file content. Now when you open the file, you should see something like this

    [​IMG]

    An interesting thing to note here is, if there is no file already present in the directory. A new file will be automatically created and it will contain only single line of the statement we write to it.

    Apart from append mode, there are also other modes like in, out, trunk and binary which perform different functions as described below

    ios::in - Open File for input operations only
    ios::eek:ut - Open File for output operations only
    ios::binary - Open file in binary mode.
    ios::ate - Used to Set the starting position at the end of the file. By Default the initial position is the beginning of the file.
    ios::app - Append the content at the end of the file
    ios::trunc - Files previous content is deleted and replaced by the new one.

    Reading Data from File



    In our previous examples, we explained how can we write and append data to a file. Now you must be thinking how to retrieve contents of data from a file. In Example3, I will show this to you.

    Example3
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    int main()
    {
        string linesread;
        ifstream IFileObject ("D:\\ExampleFile.txt");
        if (IFileObject.is_open())
        {
            while ( getline (IFileObject, linesread) )
            {
                cout << linesread << endl;
            }
            IFileObject.close();
        }
        else cout << "File cannot be read";
    }
    
    In Example3, first of all we have replaced the ofstream object by ifstream object because now we want to read the contents of the file. Note, here we did not call the open function because we do not want to open the file for writing. Instead we simply passed the path and file name in the constructor of the IFileObject. Now IFileObject refers to the file ExampleFile.txt.

    Next we have placed an if condition and called ifstream class’s is_open() function. This function will return true if file has been open for reading. In cases file do not exist on the disk or cannot be read due to some other issues, is_open() will return false and the statement ‘File cannot be read’ will be printed. In case if this function returns true, real fun begins.

    Now come inside the body of the if condition. In the while loop, we have called another function getline(). This function takes input stream as the first argument and string as the second argument. It reads the data from the stream line by line. If we have three lines in the input file it will execute thrice. It returns true if there is a line left to be read from the stream. Whenever getline() function reads a line from the stream, it stores this line in the string which has been passed as the second argument. We will display this string. In this way complete contents of the file are displayed on the output screen. Remember after you executed Example2, thrice. There were four lines written in the ExampleFile.txt. In this Example3, we have read that file and have displayed its contents. The output of the Example3 is as follows.

    Output3

    [​IMG]

    You can see that we have read all the lines that we written to the ExampleFile.txt in example2.

    Randomly Reading File Content Using seekg()

    Till, now we have read data sequentially. We started from the first character of the first row and sequentially displayed all the data. However, we can also randomly access the data of the file using a built in ifstream class method known as seekg(). This method has several overloads but in our next example, we are going to show that how can you access a string of content from in-between. For Example, if you want to start reading the string from the 9th character of the line. You can do so by using something like seekg(9). This way the compiler will went straight to the 9th character of the string and will display the remaining line. Have a look at Example4 for this concept.

    Example4
    Code:
    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    int main()
    {
        ifstream IFileObject("D:\\ExampleFile.txt");
        if (!IFileObject)
        {
            cout << "File cannot be opened" << endl;
            exit(1);
        }
        string lineread;
     
        IFileObject.seekg(9); // move to 9th character
        // print the remaining line
        getline(IFileObject, lineread);
        cout << lineread << endl;
     
        getchar(); // Just To Prevent Screen from Disappearing
        cin.get(); // Just To Prevent Screen from Disappearing
    }
    In Example4, everything is similar to Example3 with an exception that we have used seekg() function to move to 9th character in the string by writing
    Code:
    IFileObject.seekg(9);
    Now, the contents of the file ExampleFile.txt would be read from the 9th character. The output of Example4 is as follows

    Output4

    [​IMG]

    From the output, it is quite clear that seekg() has moved the cursor to 9th character and the string which has been read will be displayed starting from that character as seen in the output.

    Like open function, seekg() has several overloads which can be used to access different locations in a while. I would recommend you to further explore the seekg() function.

    In this tutorial we explained basics of file handling in C++. If you are not able to understand anything in this tutorial, leave a reply in the comment box and I will get back to you. Also, for more interesting tutorials, keep visiting this site.
     
    Last edited by a moderator: Jan 21, 2017

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice