C++ PROGRAMMING:Module 14: File I/O

Mastering module 14: file i/o concepts and implementation.

File I/O

File I/O (Input/Output) allows programs to read from and write to files. It's essential for data persistence and working with external data.

File Streams

C++ uses streams for file operations:

  • `ifstream`: Input file stream (reading)
  • `ofstream`: Output file stream (writing)
  • `fstream`: File stream (both reading and writing)

Opening Files

Basic File Opening

#include <fstream>
using namespace std;

// Open for reading
ifstream inputFile("data.txt");

// Open for writing
ofstream outputFile("output.txt");

// Open for both
fstream file("data.txt", ios::in | ios::out);

File Modes

ios::in      // Open for reading
ios::out     // Open for writing
ios::app     // Append mode
ios::ate     // Seek to end on open
ios::trunc   // Truncate file (default for ofstream)
ios::binary  // Binary mode

Checking File Open

ifstream file("data.txt");
if (!file.is_open()) {
    cerr << "Cannot open file!" << endl;
    return 1;
}

// Or
if (!file) {
    cerr << "File error!" << endl;
}

Reading from Files

Reading Line by Line

ifstream file("data.txt");
string line;

while (getline(file, line)) {
    cout << line << endl;
}

Reading Word by Word

ifstream file("data.txt");
string word;

while (file >> word) {
    cout << word << " ";
}

Reading Character by Character

ifstream file("data.txt");
char ch;

while (file.get(ch)) {
    cout << ch;
}

Reading Numbers

ifstream file("numbers.txt");
int num;

while (file >> num) {
    cout << num << " ";
}

Writing to Files

Writing Text

ofstream file("output.txt");
file << "Hello, World!" << endl;
file << "Line 2" << endl;

Appending to Files

ofstream file("output.txt", ios::app);
file << "New line appended" << endl;

Writing Numbers

ofstream file("numbers.txt");
int num = 42;
double value = 3.14;

file << num << " " << value << endl;

File Position Operations

Getting File Position

ifstream file("data.txt");
streampos position = file.tellg();  // Get position

Setting File Position

file.seekg(0, ios::beg);  // Beginning
file.seekg(0, ios::end);  // End
file.seekg(10, ios::cur); // 10 bytes from current

File Status

Checking File State

ifstream file("data.txt");

if (file.good()) {
    // File is good
}

if (file.eof()) {
    // End of file reached
}

if (file.fail()) {
    // Operation failed
}

if (file.bad()) {
    // Serious error
}

Clearing File State

file.clear();  // Clear error flags

Binary File I/O

Writing Binary Data

ofstream file("data.bin", ios::binary);
int num = 42;

file.write(reinterpret_cast<const char*>(&num), sizeof(num));

Reading Binary Data

ifstream file("data.bin", ios::binary);
int num;

file.read(reinterpret_cast<char*>(&num), sizeof(num));

String Streams

String streams allow treating strings as streams:

#include <sstream>
using namespace std;

// String to number
string str = "42";
istringstream iss(str);
int num;
iss >> num;

// Number to string
ostringstream oss;
oss << 42;
string result = oss.str();

Best Practices

  1. ✅ Always check if file opened successfully
  2. ✅ Close files explicitly (or use RAII)
  3. ✅ Use RAII for automatic file closing
  4. ✅ Handle errors gracefully
  5. ✅ Use appropriate mode (text vs binary)
  6. ✅ Check file state after operations
  7. ✅ Use `getline` for reading lines
  8. ✅ Prefer string streams for in-memory operations

Common Patterns

Pattern 1: RAII File Wrapper

class FileReader {
    ifstream file;
public:
    FileReader(const string& filename) : file(filename) {
        if (!file.is_open()) {
            throw runtime_error("Cannot open file");
        }
    }
    ~FileReader() { file.close(); }
    ifstream& get() { return file; }
};

Pattern 2: Read Entire File

string readFile(const string& filename) {
    ifstream file(filename);
    ostringstream buffer;
    buffer << file.rdbuf();
    return buffer.str();
}

Common Mistakes

  • ❌ Not checking if file opened
  • ❌ Forgetting to close files
  • ❌ Not handling file errors
  • ❌ Using wrong file mode
  • ❌ Not checking file state
  • ❌ Mixing text and binary modes
  • ❌ Not using RAII for file management

Next Module

In Module 15, we'll learn about Concurrency and Multithreading - running multiple operations simultaneously in C++!

Hands-on Examples

Basic File Reading

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

int main() {
    // Create a sample file first
    {
        ofstream createFile("sample.txt");
        createFile << "Line 1: Hello, World!" << endl;
        createFile << "Line 2: C++ File I/O" << endl;
        createFile << "Line 3: Reading files" << endl;
    }
    
    cout << "=== Reading File Line by Line ===" << endl;
    ifstream file("sample.txt");
    
    if (!file.is_open()) {
        cerr << "Error: Cannot open file!" << endl;
        return 1;
    }
    
    string line;
    int lineNumber = 1;
    
    while (getline(file, line)) {
        cout << "Line " << lineNumber << ": " << line << endl;
        lineNumber++;
    }
    
    file.close();
    
    cout << "\n=== Reading File Word by Word ===" << endl;
    ifstream file2("sample.txt");
    string word;
    
    while (file2 >> word) {
        cout << word << " ";
    }
    cout << endl;
    
    file2.close();
    
    return 0;
}

Basic file reading uses ifstream. Check if file opened with is_open(). Use getline() to read line by line. Use >> operator to read word by word. Always close files when done. File automatically closes when stream object is destroyed.