C++ Basic Operations on Binary Files

Let's now learn about basic operations on files. The operations that you have learned so far are applicable to both text and binary files. The only difference is that when working with binary files, you do need to prefix file modes with ios::binary at the time of opening the file. You have learned how to create files (open them in ios::out or ios::app mode, which will create a file if it doesn't exist already), how to read records from binary files (call the read() function through a stream object to which a file is attached), and how to write records in binary files (call the write() function through a stream object to which a file is attached).

Here, in this post, we will perform the following basic operations on binary files:

Let's start with the searching operation.

Searching in C++

We can perform a search in a binary file opened in input mode by reading each record and then checking whether it is our desired record or not. For example, if you want to find a record for a student with the roll number 1 in file marks.dat. Therefore, you can implement this search process in C++ in two ways:

  1. with records implemented through structures
  2. with records implemented through classes.

When records are implemented through structures, you can perform searches, as demonstrated in the following examples:

struct student
{
   int rollno;
   char name[20];
   char course[5];
   float marks;
   char grade;
}stud1;

ifstream fin("marks.dat", ios::in | ios::binary);
:                                              // Read the roll number to be searched for 

while(!fin.eof())
{
   fin.read((char *)&stud1, sizeof(stud1));    // read record
   if(stud1.rollno == rn)                      // If true, a record is found.
   {
      :                                        // Here, you can process the desired record. 

      found = 'y';                             // After processing, you may jump from the
      break;                                   // loop employed for searching purposes
   }
}

if(found == 'n')                               // record not found
{
   :                                           // Display the error message here
                                               // or continue with the process as desired.
}

C++ Searching Example

Let's look at an example to get a better understanding of C++ searching operations. Here's an example program in C++ that shows how to search for binary files.

#include <iostream>
#include <fstream>
using namespace std;

class student
{
   int rollno;
   char name[20], course[5], grade;
   float marks;

public:
   void getdata()
   {
      cout << "Roll Number: ";
      cin >> rollno;
      cout << "Name: ";
      cin >> name;
      cout << "Course: ";
      cin >> course;
      cout << "Mark: ";
      cin >> marks;

      if (marks >= 75)
         grade = 'A';
      else if (marks >= 60)
         grade = 'B';
      else if (marks >= 50)
         grade = 'C';
      else if (marks >= 40)
         grade = 'D';
      else
         grade = 'F';
   }

   void putdata()
   {
      cout << "Roll Number: " << rollno << "\tName: " << name << "\n";
      cout << "Mark: " << marks << "\tGrade: " << grade << "\n";
   }

   int getrno()
   {
      return rollno;
   }
} stud1;

int main()
{
   fstream fio("marks.dat", ios::in | ios::out);
   char ans = 'y';
   while (ans == 'y' || ans == 'Y')
   {
      stud1.getdata();
      fio.write((char *)&stud1, sizeof(stud1));
      cout << "A new record has been added to the file. \n";
      cout << "\nWant to enter more? (y/n): ";
      cin >> ans;
   }

   int rno;
   long pos;
   char found = 'f';

   cout << "\nEnter the student's roll number to be searched for: ";
   cin >> rno;

   fio.seekg(0);
   while (!fio.eof())
   {
      pos = fio.tellg();
      fio.read((char *)&stud1, sizeof(stud1));
      if (stud1.getrno() == rno)
      {
         stud1.putdata();
         fio.seekg(pos);
         found = 't';
         break;
      }
   }
   if (found == 'f')
   {
      cout << "\nThe record was not found in the file. \n";
      return 0;
   }
   fio.close();

   return 0;
}

The following snapshot shows the initial output produced by the above program, illustrating the searching operation on a file in C++.

c++ basic operations on binary files

Now provide the input. Assume you type "123940309" as the roll number and hit the ENTER key, then "William" as the name and hit the ENTER key, "CS" as the course and hit the ENTER key, and "98" as the mark and hit the ENTER key. Here's the sample run with these parameters:

c++ searching on file

Enter another student record and type "n" to skip entering additional data. Now, type a student's roll number to find out more about them. The sample run is depicted in the following snapshot.

c++ searching on file example program

If the records are implemented as classes, you may need to add an additional accessor function in the class's public: section that returns the value of the data member to which the user-specified search value is to be compared. This was not necessary with structures because all data members were public by default and thus accessible via a structure variable. Private data members, on the other hand, cannot be accessed via an object. To read the value of a private data member, a function in the public section is added that returns this value. The remainder of the processing is identical to that of the structures. Here's an example of code that demonstrates this:

class student
{
   int rollno;
   char name[20];
   char course[5];
   float marks;
   char grade;

   public:
      void getdata();
      void putdata();
      int getrno()               // This function returns the private member rollno's value.
      {
         return rollno;
      }
}stud1;

ifstream fin("marks.dat", ios::in);
:                                // read roll number to be looked up

while(!fin.eof())
{
   fin.read((char *)&stud1, sizeof(stud1));
   if(stud1.getrno() == rno)     // retrieve the value of a private member and compare
   {
      :                          // Here, you can process the desired record.

      found = 't';
      break;
   }
}
if(found=='n')                   // If no record is found
{
   :                             //display message for "not found"
}

Let's take an example for a complete understanding of the searching operations on the records implemented through classes in C++.

#include <iostream>
#include <fstream>
using namespace std;

class student
{
   int rollno;
   char name[20], course[5], grade;
   float marks;

public:
   void getdata()
   {
      cout << "Roll Number: ";
      cin >> rollno;
      cout << "Name: ";
      cin >> name;
      cout << "Course: ";
      cin >> course;
      cout << "Mark: ";
      cin >> marks;

      if (marks >= 75)
         grade = 'A';
      else if (marks >= 60)
         grade = 'B';
      else if (marks >= 50)
         grade = 'C';
      else if (marks >= 40)
         grade = 'D';
      else
         grade = 'F';
   }

   void putdata()
   {
      cout << name << ", roll number " << rollno << ", has ";
      cout << marks << " percent of the marks and " << grade << " grade.\n";
   }

   int getrno()
   {
      return rollno;
   }
} stud1;

int main()
{
   ofstream fout("marks.dat", ios::out);
   char ans = 'y';
   while (ans == 'y' || ans == 'Y')
   {
      stud1.getdata();
      fout.write((char *)&stud1, sizeof(stud1));
      cout << "A new record has been added to the file.\n";
      cout << "\nWant to enter more? (y/n): ";
      cin >> ans;
   }
   fout.close();

   int rno;
   char found;
   ifstream fin("marks.dat", ios::in);

   found = 'n';
   cout << "Enter the student's roll number to be searched for: ";
   cin >> rno;

   while (!fin.eof())
   {
      fin.read((char *)&stud1, sizeof(stud1));
      if (stud1.getrno() == rno)
      {
         cout << "The record was found at roll number " << rno << ". Here is the record.\n";
         stud1.putdata();
         found = 't';
         break;
      }
   }
   if (found == 'n')
   {
      cout << "\nThe record was not found in the file.\n";
      return 0;
   }
   fin.close();

   return 0;
}

Following is a small sample run of the above program, just for your understanding.

Roll Number: 43052304
Name: Julia
Course: IT
Mark: 90
A new record has been added to the file.

Want to enter more? (y/n): n
Enter the student's roll number to be searched for: 43052304
The record was found at roll number 43052304. Here is the record.
Julia, roll number 43052304, has 90 percent of the marks and A grade.

Process returned 0 (0x0)   execution time : 22.181 s

Appending Data in C++

To append data to a file, the file is opened with the following two specifications:

  1. file is opened in output mode
  2. file is opened in ios::app mode

Once the file gets opened in ios::app mode, the previous records (information) are retained, and new data gets appended to the file.

Consider the following code fragment, which adds new records to the file marks.dat:

class student
{
   :
}stud1;
ofstream fout;
fout.open("marks.dat", ios::app | ios::binary);

// Repeat the following lines as many times as necessary
{
   stud1.getdata();                               // Read Record
   fout.write((char *) &stud1, sizeof(stud1));    // record appended
}

C++ Appending Data Example

The only change you need to make to create an example of appending data to a file in C++ is to replace the following statement from the previous program:

ofstream fout("marks.dat", ios::out);

with

ofstream fout("marks.dat", ios::app);

Everything will be the same as the previous program, except for the following statement:

cout << "A new record has been added to the file.\n";

Because this program is created to append the data, you can write "appended" in place of "added." For example, use the following statement instead of the preceding one.

cout << "A new record has been appended to the file.\n";

C++ Inserting Data in a Sorted File

In order to insert data into a sorted file, first its appropriate position must be determined, then records in the file that came before this determined position must be copied to a temporary file, then the new record that is to be inserted must be copied, and finally the remaining records from the file must also be copied. This process is repeated until the data has been successfully inserted.

For example, records in marks.dat are sorted in ascending order on the basis of rollno, assuming that there are about 10 records in the file marks.dat. Now a new record with roll number 5 is to be inserted. It will be accomplished as follows:

(i) Determining the appropriate position. If the rollno of the new record is NREC, in which rollno 5 is less than the rollno of the very first record, then the position is 1, where the new record is to be inserted, as it will be inserted at the beginning of the file to maintain the sorted order.

If the rollno of the new record (5 here) satisfies the following condition for two consecutive records, say (pth and (p + 1)th).

if prev.getrno() <= NREC.getrno() && (NREC.getrno() <= next.getrno())

then the appropriate position will be prev + 1, i.e., p + 1.

And if the rollno of the new record is greater than the rollno of the last record (say, the nth record), then the appropriate position will be n+1.

(ii) Copy the records prior to their determined position to a temporary file, say temp.dat.

(iii) Append the new record to the temporary file temp.dat.

(iv) Now append the rest of the records in the temporary file temp.dat.

(v) Delete the file marks.dat by using the following code:

remove("marks.dat");

(vi) Now, rename the file temp.dat as marks.dat as follows:

rename("temp.dat", "marks.dat");

Deleting a Record in C++

To delete a record, the following procedure is carried out:

(i) Firstly, determine the position of the record to be deleted by performing a search in the file.

(ii) Keep copying the records other than the record to be deleted in a temporary file, say temp.dat.

(iii) Do not copy the record to be deleted to a temporary file, temp.dat.

(iv) Copy the rest of the records to temp.dat.

(v) Delete the original file, say marks.dat, using:

remove("marks.dat");

(vi) Rename temp.dat as marks.dat as:

rename("temp.dat", "marks.dat");

Modifying data in C++

To modify a record, the file is opened in I/O mode, and an important step is performed that gives the beginning address of the record being modified. After the record is modified in memory, the file pointer is once again placed at the beginning position of this record, and then the record is rewritten. The following code illustrates it:

class student
{
   :
   void modify();
}stud1;

fstream fio("marks.dat", ios::in | ios::out);
/* Read the rollno whose data is to be changed. */
long pos;
while(!fio.eof())
{
   pos = fio.tellg()                              // determine the beginning position of the record
   fio.read((char *) &stud1, sizeof(stud1));
   if(stud1.getrno() == rn)                       // This is the record that needs to be modified.
   {
      stud1.modify();                             // get the new data.
      fio.seekg(pos);                             // Place the file pointer at the beginning record position.
      fio.write((char *) &stud1, sizeof(stud1));  // now write the modified record.
   }
}

More Examples

C++ Quiz


« Previous Tutorial Next Tutorial »


Liked this post? Share it!