Introduction: Why Working with the File System in C++ is Fundamental
\n\nAny serious program will sooner or later need to save data to disk or read it from there. Configuration files, logs, databases, user documents — all of this requires the ability to interact with the file system. In C++, there are two main approaches for this: classic input/output streams (the <fstream> library) and the more modern, higher-level std::filesystem (since C++17).
In this article, we will cover practical scenarios: from simple reading and writing of text files to navigating directories and error handling. All examples are written in C++17/20 and are ready to use in your projects.
\n\n1. Basics: Reading and Writing Files with fstream
\n\nThe <fstream> library provides three main classes: ifstream (input stream — reading), ofstream (output stream — writing), and fstream (bidirectional stream). Let's look at them with examples.
1.1. Writing to a Text File
\n\nThe simplest way to write data is to use ofstream. If the file does not exist, it will be created. If it exists, it will be overwritten (ios::trunc mode by default).
#include <iostream>\n#include <fstream>\n#include <string>\n\nint main() {\n std::ofstream outFile("example.txt");\n if (!outFile) {\n std::cerr << "Error opening file for writing\\n";\n return 1;\n }\n\n outFile << "Hello, C++ file system!\\n";\n outFile << "Line number 2\\n";\n outFile << 42 << " — is a number.\\n";\n\n outFile.close(); // closing manually is optional, but good practice\n std::cout << "Data written.\\n";\n return 0;\n}\n\n1.2. Reading from a Text File
\n\nFor reading, we use ifstream. The most reliable way is to read line by line using std::getline.
#include <iostream>\n#include <fstream>\n#include <string>\n\nint main() {\n std::ifstream inFile("example.txt");\n if (!inFile) {\n std::cerr << "File not found or cannot be opened\\n";\n return 1;\n }\n\n std::string line;\n while (std::getline(inFile, line)) {\n std::cout << "Read: " << line << '\\n';\n }\n\n inFile.close();\n return 0;\n}\n\n1.3. Open Modes and Binary Files
\n\nYou can combine open flags: ios::app (append), ios::binary (binary mode), ios::ate (seek to end). For binary files, use the read() and write() methods.
#include <fstream>\n#include <vector>\n\n// Example: writing and reading a vector of integers in binary format\nvoid saveVector(const std::string& filename, const std::vector<int>& data) {\n std::ofstream file(filename, std::ios::binary);\n if (!file) return;\n file.write(reinterpret_cast<const char*>(data.data()), data.size() * sizeof(int));\n}\n\nstd::vector<int> loadVector(const std::string& filename) {\n std::ifstream file(filename, std::ios::binary);\n if (!file) return {};\n file.seekg(0, std::ios::end);\n size_t size = file.tellg() / sizeof(int);\n file.seekg(0, std::ios::beg);\n std::vector<int> data(size);\n file.read(reinterpret_cast<char*>(data.data()), size * sizeof(int));\n return data;\n}\n\n2. Modern Approach: std::filesystem (C++17)
\n\nStarting from C++17, the standard library includes the <filesystem> module, which allows you to work with paths, files, and directories at a high level, cross-platform.
2.1. Checking Existence and Getting File Information
\n\nMore