C++'s <fstream> provides object-oriented file streams — ifstream for reading, ofstream for writing, fstream for both — that plug directly into the same <</>> operators used for console I/O.
#include <fstream>
#include <sstream>
#include <string>
int main() {
std::ofstream outFile("notes.txt"); // opens for writing automatically
if (!outFile) { // checks the stream's state directly
std::cerr << "Failed to open file\n";
return 1;
}
outFile << "Line 1\n" << "Line 2\n";
outFile.close();
std::ifstream inFile("notes.txt");
std::string line;
while (std::getline(inFile, line)) { // reads one line at a time
std::cout << "Read: " << line << "\n";
}
inFile.close();
std::stringstream ss("42 3.14 hello"); // treat a string like a stream
int i; double d; std::string s;
ss >> i >> d >> s; // parses each token by type
return 0;
}
Unlike C's FILE*, an ifstream/ofstream is the file — opening it is usually done directly in the constructor (std::ofstream outFile("notes.txt")), and its destructor automatically closes the file when it goes out of scope, another example of RAII in action; calling .close() explicitly is good practice but not strictly required for correctness.
A stream's boolean state (checked with if (!outFile) or if (outFile)) reflects whether the last operation succeeded — this replaces checking for a NULL return value the way C's fopen requires, and the same pattern works for detecting end-of-file or a failed read inside a loop condition, as while (std::getline(inFile, line)) does above (it evaluates to false once there are no more lines).
std::stringstream (from <sstream>) treats an in-memory string as if it were a stream, letting you parse a line of mixed-type data (numbers and words together) using the same >> extraction syntax as reading from a file or the keyboard — a common, convenient technique for splitting and converting text without manual string manipulation.