File Handling in C++

File Handling in C++

2021, Mar 28    

File handling is a crucial aspect of C++ programming that allows you to store and retrieve data from files. This guide will walk you through the fundamentals of file handling in C++ and provide practical examples.

Table of Contents

  1. File Streams
  2. Basic File Operations
  3. Text File Operations
  4. Binary File Operations
  5. File Position Pointers
  6. Error Handling
  7. Best Practices

File Streams

C++ provides three main classes for file handling in the <fstream> header:

  • ofstream: Output file stream for writing to files
  • ifstream: Input file stream for reading from files
  • fstream: General file stream for both reading and writing
#include <fstream>
#include <iostream>
using namespace std;

int main() {
    // Create an output file stream
    ofstream outFile;
    
    // Create an input file stream
    ifstream inFile;
    
    // Create a general file stream
    fstream file;
    
    return 0;
}

Basic File Operations

Opening a File

Files can be opened in different modes:

// Open for writing (creates new file or overwrites existing)
outFile.open("example.txt", ios::out);

// Open for reading
inFile.open("example.txt", ios::in);

// Open for appending
outFile.open("example.txt", ios::app);

// Open for both reading and writing
file.open("example.txt", ios::in | ios::out);

Common file modes:

  • ios::in: Open for reading
  • ios::out: Open for writing
  • ios::app: Append to file
  • ios::ate: Open and seek to end
  • ios::binary: Open in binary mode
  • ios::trunc: Truncate file if it exists

Closing a File

Always close files when you’re done:

outFile.close();
inFile.close();
file.close();

Text File Operations

Writing to a Text File

ofstream outFile("example.txt");
if (outFile.is_open()) {
    outFile << "Hello, World!" << endl;
    outFile << "This is a new line." << endl;
    outFile.close();
} else {
    cerr << "Unable to open file" << endl;
}

Reading from a Text File

ifstream inFile("example.txt");
string line;

if (inFile.is_open()) {
    while (getline(inFile, line)) {
        cout << line << endl;
    }
    inFile.close();
} else {
    cerr << "Unable to open file" << endl;
}

Binary File Operations

Writing Binary Data

struct Person {
    char name[50];
    int age;
    double salary;
};

Person person = {"John Doe", 30, 75000.0};

ofstream outFile("person.dat", ios::binary);
if (outFile.is_open()) {
    outFile.write(reinterpret_cast<char*>(&person), sizeof(Person));
    outFile.close();
}

Reading Binary Data

Person person;
ifstream inFile("person.dat", ios::binary);

if (inFile.is_open()) {
    inFile.read(reinterpret_cast<char*>(&person), sizeof(Person));
    cout << "Name: " << person.name << endl;
    cout << "Age: " << person.age << endl;
    cout << "Salary: " << person.salary << endl;
    inFile.close();
}

File Position Pointers

You can manipulate the file position pointer using these functions:

// Get current position
streampos pos = file.tellg();

// Set position from beginning
file.seekg(0, ios::beg);

// Set position from end
file.seekg(-10, ios::end);

// Set position from current position
file.seekg(5, ios::cur);

Error Handling

Always check for errors when working with files:

ifstream inFile("example.txt");

if (!inFile) {
    cerr << "Error opening file" << endl;
    return 1;
}

// Check for specific error states
if (inFile.fail()) {
    cerr << "Input operation failed" << endl;
}

if (inFile.bad()) {
    cerr << "Fatal error occurred" << endl;
}

if (inFile.eof()) {
    cout << "End of file reached" << endl;
}

Best Practices

  1. Always Check File Open Status
    if (!file.is_open()) {
        // Handle error
    }
    
  2. Use RAII (Resource Acquisition Is Initialization)
    {
        ofstream file("example.txt");
        // File will be automatically closed when going out of scope
    }
    
  3. Handle Exceptions
    try {
        ofstream file("example.txt");
        if (!file) throw runtime_error("Could not open file");
        // File operations
    } catch (const exception& e) {
        cerr << "Error: " << e.what() << endl;
    }
    
  4. Use Appropriate File Modes
    • Use ios::binary for non-text data
    • Use ios::app for appending
    • Use ios::trunc carefully
  5. Close Files Properly
    • Always close files when done
    • Use RAII when possible
    • Check for errors after closing
  6. Buffer Management
    // Flush buffer manually if needed
    file.flush();
       
    // Disable buffering for critical operations
    file.setf(ios::unitbuf);
    

Remember that proper file handling is essential for data integrity and program reliability. Always follow these best practices and handle errors appropriately in your C++ programs.