cpp
Advanced Topics
09_Advanced_Topics⚙️cpp
/**
* ============================================================
* 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
*/