File Handling:


Up to this point, we have gathered sufficient tools to create advanced programs and store data on disk. Now, we will create a program called "InfoBrother DMS." This program will be capable of writing records to a file, reading records from a file, modifying existing records, searching for records in a file, and deleting any records from a file.

In this tutorial, we will discuss some methods used in our program. The complete code is provided in the link below. Please download the project using the link.

Our DMS can perform the following operations:

In our program, we have two classes. The first class handles user data, while the second class stores that data in a file. To display the stored data, the first class retrieves the information from the file. Let's discuss some important methods of our project.

Get Employee ID:

// This pointer function will store the employee's ID number.
char *getEmp_ID() {
   return employe_ID; // Return employee ID
}

The above function is a pointer function that points to a char. *getEmp_IDwill point to the employee's ID employe_ID. When the user enters the employee ID, this pointer will store its location and provide the value when requested.

Write Data into the File:

void WriteEmployee() {
    int more; // Variable to control the loop
    fp.open("Employe.DAT", ios::out | ios::app);
    if (!fp) { // Error checker
        cout << "\n\a Error...!! Employee file could not open";
        getch(); // Wait for user input
        return;
    }

    do { // Loop to repeat data entry until 2 is pressed
        Emp.getEmp_data(); // Call function to get employee data
        fp.write((char*)&Emp, sizeof(Emp));
        cout << "\n\n\a Press 1 to Enter More Data: " << endl;
        cout << " Press 2 to Return to Main Menu: " << endl;
        cout << " Option: ";
        cin >> more;
    } while (more == 1); // Continue entering data while the entered number is 1
    fp.close(); // Close the file
}

The WriteEmployeefunction will open the file using the file pointer fpin appending mode. If the file does not exist, the pointer will create a new file. Using a do-while loop, our program will write the entered information into the file with the help of the write()method.

Modify Previous Record:

// This function will be used to modify employee data
void W_ModifyEmp()
{
    int found = 0; // Indicator if data is found (1 if found, 0 if not)
    char n[20]; // To store the user ID

    cout << "\n\n\a Enter User ID" << endl;
    cout << " \nUser ID: ";
    cin >> n;

    fp.open("Employe.DAT", ios::in | ios::out);
    if (!fp) // Error checker
    {
        cout << "\n\a Error...!! Employee file could not open";
        getch(); // Wait for user input
        return;
    }

    while (fp.read((char*)&Emp, sizeof(Emp)))
    {
        if (strcmpi(Emp.getEmp_ID(), n) == 0) // If entered ID matches any data
        {
            Emp.showemp_data(); // Show the record
            cout << "\n Enter New Data To Modify: " << endl;
            Emp.modifyEmp_data();
            int position = -1 * sizeof(Emp); // Move position back by the size of Emp
            fp.seekp(position, ios::cur); // Set writing pointer to current position
            fp.write((char*)&Emp, sizeof(Emp));
            found = 1; // Data found, so set found to 1
        }
    }
    fp.close();
    if (found == 0)
    {
        cout << "\n\n\a Record Not found: " << endl;
    }
    else
    {
        cout << "\n\t\a Employee Data Modified Successfully:" << endl;
    }
    getch();
}

This is an important function, though a bit complex. We ask the user to enter the ID to search for the record. The program stores the ID in the variable n, then opens the file for reading. Using the strcmpi()function, we compare the ID stored in the variable nwith the ID stored in the pointer variable getEmp_ID(). If the ID matches, we open that record and modify it. Using the seekp()function, we set the position of the file pointer to the specific location (at the start of that record) and overwrite the record. We use the foundvariable to check if the record was found and modified. If foundremains 0, it means the record was not found.

Search for Any Record from the File:

// This function allows us to find any data from all stored records
void W_SearchEmp()
{
    int found = 0; // Indicator if the record is found (1 if found, 0 if not)
    char n[20]; // To store the employee ID from the user

    cout << "\n\n\a Enter Employee ID: " << endl;
    cout << " Employee ID: ";
    cin >> n;

    fp.open("Employe.DAT", ios::in);
    if (!fp) // Error checker
    {
        cout << "\n\a Error...!! Employee file could not open";
        getch(); // Wait for user input
        return;
    }

    while (fp.read((char*)&Emp, sizeof(Emp)))
    {
        if (strcmpi(Emp.getEmp_ID(), n) == 0) // If entered ID matches any data
        {
            Emp.showemp_data(); // Call function to show data
            found = 1; // Data found, so set found to 1
        }
    }
    fp.close();
    if (found == 0) // If the record is not found, found will be 0
    {
        cout << "\n\n\a Record Not Found: " << endl;
    }
    getch();
}

Using the above function, we can search for any stored record from the file. This function compares the user-entered ID and getEmp_IDusing the strcmpi()function. If the program finds the record, it will display it on the screen and assign 1 to the variable found. If foundremains 0, it means the record was not found.

Delete Any Record from the File:

// This function will be used to delete any record
void deleteEmp()
{
    int found = 0; // Indicator if data is found (1 if found, 0 if not)
    char n[20]; // To get the user ID from the user

    cout << "\n\n\a Enter User ID: " << endl;
    cout << " User ID: ";
    cin >> n;

    fp.open("Employe.DAT", ios::out | ios::in);
    if (!fp) // Error checker
    {
        cout << "\n\a Error...!! Employee file could not open";
        getch(); // Wait for user input
        return;
    }

    fstream fp2; // Temporary file pointer
    fp2.open("temp.DAT", ios::out);
    if (!fp2) // Error checker
    {
        cout << "\n\a Error...!! Temporary file could not open";
        getch(); // Wait for user input
        return;
    }

    fp.seekg(0, ios::beg); // Set the reading pointer at the beginning
    while (fp.read((char*)&Emp, sizeof(Emp)))
    {
        // Read all data, and if the entered ID matches any stored ID, skip it and copy all other data
        if (strcmpi(Emp.getEmp_ID(), n) != 0)
        {
            // Copy all data to the temp file except the matched record
            fp2.write((char*)&Emp, sizeof(Emp));
        }
        else
        {
            found = 1; // As we found the record, set found to 1
        }
    }

    fp.close();
    fp2.close();

    remove("Employe.DAT"); // Delete the Employee file
    rename("temp.DAT", "Employe.DAT"); // Rename the temp file to the employee file
    if (found == 0) // If found is 0, it means the record was not found
    {
        cout << "\n\n\a Record Not Found: " << endl;
    }
    else
    {
        cout << "\n\t\a Employee Data Deleted Successfully:" << endl;
    }
    getch();
}

To delete any record, we first need to search for that record. As previously discussed, we search for the record and set the input pointer at the beginning of the file using the seekg()function. We open two files: the existing file, where we store our records, which we open for reading, and a temporary file for writing. If the program finds the data to delete, it will copy all records to the temporary file except the matched one. We then delete the old file and rename the temporary file..