Files and Streams in Depth
fstream, formatting, binary vs text, and the stream error state
Big Idea: In C++ every input and output source — the keyboard, the screen, a file on disk, even a string in memory — is modelled by the same abstraction: a stream. Once you understand streams, reading a file is barely different from reading
std::cin. This topic takes you past the beginner "open, read, close" recipe into the details that matter in real programs: open modes, output formatting, the difference between text and binary I/O, and how to check whether an operation actually succeeded.
By the end you will be able to:
- choose the right stream type and open mode for a job,
- read files robustly with the correct loop idiom,
- control output layout with manipulators (
setw,setprecision,fixed,hex, ...), - read and write binary data and know when text mode betrays you,
- inspect the error state (
good,eof,fail,bad) and recover from it.
1. The stream family
A stream is an object that represents a flowing sequence of bytes between your program and some device. The standard library gives you a small hierarchy, all declared in the <iostream>, <fstream> and <sstream> headers:
std::istream— a base type you can read from (std::cinis one).std::ostream— a base type you can write to (std::cout,std::cerr).std::ifstream— an input file stream.std::ofstream— an output file stream.std::fstream— a file stream that can do both.std::istringstream/std::ostringstream— streams backed by an in-memory string, perfect for parsing and building text.
The payoff is uniformity: any function that takes an std::istream& will happily accept a std::cin, an std::ifstream, or an std::istringstream. Write your parsing code once and it works on files, the console, and test strings.
fstream inherits from both sides, so it can read and write. Any code written against the base types works on every concrete stream.