10.1 Text File I/O and Paths
Files store data persistently. Variables in memory disappear when a program ends, but data written to a file can remain. File I/O means input from files and output to files.
C++ has older C-style file APIs such as FILE*, but in this chapter we use C++ style file I/O: std::ifstream, std::ofstream, std::fstream, and std::filesystem::path.
filesystem::path and Streams
std::filesystem::path represents where a file or directory is. File streams perform the actual reading and writing.
#include <filesystem>
#include <fstream>
#include <iostream>
#include <sstream>
int main() {
std::filesystem::path path = "notes.txt";
std::ifstream input(path);
if (!input) {
std::cout << "Could not open notes.txt" << std::endl;
return 1;
}
std::ostringstream buffer;
buffer << input.rdbuf();
std::string content = buffer.str();
std::cout << content;
return 0;
}Creating std::filesystem::path path = "notes.txt"; does not read the file. Opening std::ifstream input(path); is the operation that asks the operating system for the file. The stream closes automatically when it goes out of scope.
fopen, fprintf, fscanf, and fclose. Those are C-style APIs. In C++ beginner code, prefer file streams because they fit C++ objects, RAII, and std::string.Reading Small Text Files
For small files, reading the whole file into a std::string is convenient.
std::ifstream input("quote.txt");
std::ostringstream buffer;
buffer << input.rdbuf();
std::string text = buffer.str();
std::cout << text;If you want all lines as a list, read with std::getline and push each line into a std::vector<std::string>.
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
std::ifstream input("quote.txt");
std::vector<std::string> lines;
std::string line;
while (std::getline(input, line)) {
lines.push_back(line);
}
for (std::size_t i = 0; i < lines.size(); i++) {
std::cout << (i + 1) << ": " << lines[i] << std::endl;
}Use whole-file reading when the file is comfortably small. If the file may be large, prefer line-by-line reading, which Chapter 10.2 covers.
I/O Failures
File operations can fail for reasons outside your program: the file might be missing, the path might point to a directory, permissions might block access, or the disk might be unavailable. C++ streams expose failure through stream state.
std::ifstream input("notes.txt");
if (!input) {
std::cout << "Could not read notes.txt" << std::endl;
}Some std::filesystem operations throw std::filesystem::filesystem_error.
try {
auto size = std::filesystem::file_size("notes.txt");
std::cout << size << " bytes" << std::endl;
} catch (const std::filesystem::filesystem_error& error) {
std::cout << "File operation failed: " << error.what() << std::endl;
}The important idea is not "always catch" or "always return." The important idea is to decide where the program can respond usefully.