cpp

Advanced Topics

09_Advanced_Topics⚙️
/**
 * ============================================================
 * C++ FILE HANDLING
 * ============================================================
 * 
 * This file covers:
 * - File streams (ifstream, ofstream, fstream)
 * - Text file operations
 * - Binary file operations
 * - File positioning
 * - Error handling
 * - Modern file handling with filesystem
 * 
 * Compile: g++ -std=c++17 -Wall 01_file_handling.cpp -o files
 * Run: ./files
 * 
 * ============================================================
 */

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <filesystem>
#include <iomanip>

using namespace std;
namespace fs = filesystem;

// ============================================================
// MAIN FUNCTION
// ============================================================

int main() {
    cout << "============================================" << endl;
    cout << "     C++ FILE HANDLING" << endl;
    cout << "============================================" << endl << endl;

    // ========================================================
    // PART 1: WRITING TO FILES
    // ========================================================
    
    cout << "--- PART 1: WRITING TO FILES ---" << endl << endl;
    
    // Basic file writing
    {
        ofstream outFile("example.txt");  // Opens for writing
        
        if (!outFile) {
            cerr << "Error: Could not create file!" << endl;
        } else {
            outFile << "Hello, File!" << endl;
            outFile << "This is line 2." << endl;
            outFile << "Numbers: " << 42 << ", " << 3.14159 << endl;
            
            cout << "✓ Created example.txt" << endl;
        }
        // File automatically closed when outFile goes out of scope
    }
    
    // Appending to file
    {
        ofstream appendFile("example.txt", ios::app);  // Append mode
        
        if (appendFile) {
            appendFile << "This line was appended." << endl;
            cout << "✓ Appended to example.txt" << endl;
        }
    }
    
    // Writing with explicit open/close
    {
        ofstream manualFile;
        manualFile.open("manual.txt");
        
        if (manualFile.is_open()) {
            manualFile << "Manually opened file." << endl;
            manualFile.close();
            cout << "✓ Created manual.txt" << endl;
        }
    }
    
    cout << endl;

    // ========================================================
    // PART 2: READING FROM FILES
    // ========================================================
    
    cout << "--- PART 2: READING FROM FILES ---" << endl << endl;
    
    // Read entire file line by line
    {
        ifstream inFile("example.txt");
        
        if (!inFile) {
            cerr << "Error: Could not open example.txt" << endl;
        } else {
            cout << "Contents of example.txt:" << endl;
            cout << "─────────────────────────" << endl;
            
            string line;
            while (getline(inFile, line)) {
                cout << line << endl;
            }
            cout << "─────────────────────────" << endl;
        }
    }
    
    // Read word by word
    {
        // Create a sample file
        ofstream tempOut("words.txt");
        tempOut << "apple banana cherry date elderberry";
        tempOut.close();
        
        ifstream wordFile("words.txt");
        cout << "\nWords from words.txt:" << endl;
        
        string word;
        int count = 0;
        while (wordFile >> word) {
            cout << ++count << ": " << word << endl;
        }
    }
    
    // Read entire file into string
    {
        ifstream fullFile("example.txt");
        stringstream buffer;
        buffer << fullFile.rdbuf();
        string contents = buffer.str();
        
        cout << "\nEntire file as string (length: " << contents.length() << " chars)" << endl;
    }
    
    // Read file into vector
    {
        ifstream lineFile("example.txt");
        vector<string> lines;
        string line;
        
        while (getline(lineFile, line)) {
            lines.push_back(line);
        }
        
        cout << "\nFile has " << lines.size() << " lines" << endl;
    }
    
    cout << endl;

    // ========================================================
    // PART 3: FILE OPEN MODES
    // ========================================================
    
    cout << "--- PART 3: FILE OPEN MODES ---" << endl << endl;
    
    cout << "Open mode flags:" << endl;
    cout << "─────────────────────────────────────────" << endl;
    cout << "ios::in      - Open for reading" << endl;
    cout << "ios::out     - Open for writing" << endl;
    cout << "ios::app     - Append to end" << endl;
    cout << "ios::ate     - Start at end" << endl;
    cout << "ios::trunc   - Truncate file" << endl;
    cout << "ios::binary  - Binary mode" << endl;
    
    cout << "\nCombining modes:" << endl;
    cout << "─────────────────────────────────────────" << endl;
    cout << "ios::in | ios::out  - Read and write" << endl;
    cout << "ios::out | ios::app - Write, append" << endl;
    cout << "ios::in | ios::binary - Binary read" << endl;
    
    // Example: Read and write
    {
        fstream rwFile("readwrite.txt", ios::out);
        rwFile << "Initial content" << endl;
        rwFile.close();
        
        rwFile.open("readwrite.txt", ios::in | ios::out);
        string content;
        getline(rwFile, content);
        cout << "\nRead: " << content << endl;
        
        rwFile.seekp(0, ios::end);  // Move to end
        rwFile << "Added content" << endl;
        
        rwFile.close();
        cout << "✓ Read and wrote to readwrite.txt" << endl;
    }
    
    cout << endl;

    // ========================================================
    // PART 4: BINARY FILE I/O
    // ========================================================
    
    cout << "--- PART 4: BINARY FILE I/O ---" << endl << endl;
    
    // Write binary data
    struct Record {
        int id;
        double value;
        char name[20];
    };
    
    {
        ofstream binOut("data.bin", ios::binary);
        
        Record records[] = {
            {1, 3.14, "Alpha"},
            {2, 2.71, "Beta"},
            {3, 1.41, "Gamma"}
        };
        
        binOut.write(reinterpret_cast<char*>(records), sizeof(records));
        cout << "✓ Wrote " << sizeof(records) << " bytes to data.bin" << endl;
    }
    
    // Read binary data
    {
        ifstream binIn("data.bin", ios::binary);
        
        Record readRecords[3];
        binIn.read(reinterpret_cast<char*>(readRecords), sizeof(readRecords));
        
        cout << "\nRead from binary file:" << endl;
        for (const auto& r : readRecords) {
            cout << "  ID: " << r.id 
                 << ", Value: " << r.value 
                 << ", Name: " << r.name << endl;
        }
    }
    
    // Write individual values
    {
        ofstream valOut("values.bin", ios::binary);
        
        int num = 12345;
        double pi = 3.14159;
        
        valOut.write(reinterpret_cast<char*>(&num), sizeof(num));
        valOut.write(reinterpret_cast<char*>(&pi), sizeof(pi));
        
        cout << "\n✓ Wrote int and double to values.bin" << endl;
    }
    
    // Read individual values
    {
        ifstream valIn("values.bin", ios::binary);
        
        int num;
        double pi;
        
        valIn.read(reinterpret_cast<char*>(&num), sizeof(num));
        valIn.read(reinterpret_cast<char*>(&pi), sizeof(pi));
        
        cout << "Read: num=" << num << ", pi=" << pi << endl;
    }
    
    cout << endl;

    // ========================================================
    // PART 5: FILE POSITIONING
    // ========================================================
    
    cout << "--- PART 5: FILE POSITIONING ---" << endl << endl;
    
    // Create test file
    {
        ofstream posFile("position.txt");
        posFile << "0123456789ABCDEFGHIJ";
    }
    
    {
        fstream file("position.txt", ios::in | ios::out);
        
        // tellg - get position (read)
        // tellp - put position (write)
        cout << "Initial position: " << file.tellg() << endl;
        
        // seekg - seek for reading
        // seekp - seek for writing
        
        file.seekg(5);  // Move to position 5
        char ch;
        file.get(ch);
        cout << "Char at position 5: " << ch << endl;
        
        // Seek relative to current (ios::cur)
        file.seekg(3, ios::cur);
        file.get(ch);
        cout << "After +3: " << ch << endl;
        
        // Seek relative to end (ios::end)
        file.seekg(-5, ios::end);
        file.get(ch);
        cout << "5 from end: " << ch << endl;
        
        // Modify at specific position
        file.seekp(10);
        file << "XXXX";
        
        // Read entire modified content
        file.seekg(0);
        string content;
        getline(file, content);
        cout << "Modified: " << content << endl;
    }
    
    cout << endl;

    // ========================================================
    // PART 6: ERROR HANDLING
    // ========================================================
    
    cout << "--- PART 6: ERROR HANDLING ---" << endl << endl;
    
    // Stream state flags
    ifstream testFile("nonexistent.txt");
    
    cout << "Stream state flags:" << endl;
    cout << "  good(): " << testFile.good() << endl;
    cout << "  eof():  " << testFile.eof() << endl;
    cout << "  fail(): " << testFile.fail() << endl;
    cout << "  bad():  " << testFile.bad() << endl;
    
    // Clear error flags
    testFile.clear();
    cout << "After clear(), good(): " << testFile.good() << endl;
    
    // Exception-based error handling
    {
        ifstream strictFile;
        strictFile.exceptions(ifstream::failbit | ifstream::badbit);
        
        try {
            strictFile.open("does_not_exist.txt");
        } catch (const ifstream::failure& e) {
            cout << "\nException caught: " << e.what() << endl;
        }
    }
    
    // Robust file reading
    {
        ifstream robustFile("example.txt");
        
        if (!robustFile.is_open()) {
            cerr << "Failed to open file" << endl;
        } else {
            string line;
            while (getline(robustFile, line)) {
                // Process line
            }
            
            if (robustFile.eof()) {
                cout << "\n✓ Reached end of file normally" << endl;
            } else if (robustFile.fail()) {
                cerr << "Read failed before EOF" << endl;
            }
        }
    }
    
    cout << endl;

    // ========================================================
    // PART 7: FILESYSTEM LIBRARY (C++17)
    // ========================================================
    
    cout << "--- PART 7: FILESYSTEM (C++17) ---" << endl << endl;
    
    // Current path
    cout << "Current path: " << fs::current_path() << endl;
    
    // File exists
    cout << "example.txt exists: " << fs::exists("example.txt") << endl;
    
    // File size
    cout << "example.txt size: " << fs::file_size("example.txt") << " bytes" << endl;
    
    // Create directory
    fs::create_directory("test_dir");
    cout << "✓ Created test_dir" << endl;
    
    // Copy file
    fs::copy("example.txt", "test_dir/example_copy.txt", 
             fs::copy_options::overwrite_existing);
    cout << "✓ Copied example.txt to test_dir/" << endl;
    
    // List directory
    cout << "\nDirectory contents:" << endl;
    for (const auto& entry : fs::directory_iterator(".")) {
        cout << "  " << entry.path().filename();
        if (entry.is_directory()) cout << "/";
        cout << endl;
    }
    
    // File info
    auto status = fs::status("example.txt");
    cout << "\nFile type: ";
    if (fs::is_regular_file(status)) cout << "regular file";
    else if (fs::is_directory(status)) cout << "directory";
    else cout << "other";
    cout << endl;
    
    // Remove test files
    fs::remove("test_dir/example_copy.txt");
    fs::remove("test_dir");
    cout << "\n✓ Cleaned up test_dir" << endl;
    
    cout << endl;

    // ========================================================
    // CLEANUP AND SUMMARY
    // ========================================================
    
    // Clean up created files
    fs::remove("example.txt");
    fs::remove("manual.txt");
    fs::remove("words.txt");
    fs::remove("readwrite.txt");
    fs::remove("data.bin");
    fs::remove("values.bin");
    fs::remove("position.txt");
    
    cout << "--- FILE I/O SUMMARY ---" << endl << endl;
    
    cout << "Stream Classes:" << endl;
    cout << "─────────────────────────────────────────" << endl;
    cout << "ifstream  - Input (reading)" << endl;
    cout << "ofstream  - Output (writing)" << endl;
    cout << "fstream   - Both input and output" << endl;
    
    cout << "\nImportant Methods:" << endl;
    cout << "─────────────────────────────────────────" << endl;
    cout << "open(), close(), is_open()" << endl;
    cout << "read(), write() - binary" << endl;
    cout << "getline(), >> - text" << endl;
    cout << "seekg(), seekp(), tellg(), tellp()" << endl;
    cout << "good(), eof(), fail(), bad(), clear()" << endl;
    
    cout << endl;

    cout << "============================================" << endl;
    cout << "FILE HANDLING COMPLETE!" << endl;
    cout << "============================================" << endl;

    return 0;
}

// ============================================================
// EXERCISES:
// ============================================================
/*
 * 1. Log file analyzer:
 *    - Read log file with timestamps
 *    - Filter by date range
 *    - Count error/warning/info messages
 * 
 * 2. CSV parser:
 *    - Read CSV file
 *    - Parse into struct/class
 *    - Support quoted fields with commas
 * 
 * 3. Binary database:
 *    - Store records in binary file
 *    - Support add, update, delete, search
 *    - Use file positioning for random access
 * 
 * 4. File encryption/decryption:
 *    - Read file in binary mode
 *    - Apply simple XOR encryption
 *    - Write encrypted file
 */
Advanced Topics - C++ Tutorial | DeepML