Ch11.12: C++ iostream
Overview
C++’s standard I/O library provides std::fstream, std::ifstream,
and std::ofstream. These stream classes are built on top of
std::basic_filebuf, which is the C++ runtime’s buffered file abstraction.
fast_io provides wrappers that let you bring std::basic_filebuf
into the fast_io I/O system, so you can use print,
println, and scan on them.
Standard C++ I/O: <iostream>, <fstream>, <sstream>
Before discussing how fast_io wraps C++ I/O, let’s review the standard C++
I/O library. C++ provides three main headers for I/O:
<iostream>— standard streams (std::cin,std::cout,std::cerr,std::clog)<fstream>— file streams (std::ifstream,std::ofstream,std::fstream)<sstream>— string streams (std::istringstream,std::ostringstream,std::stringstream)
Standard Streams
C++ provides four predefined streams:
std::cin— standard input (usually keyboard)std::cout— standard output (usually terminal)std::cerr— standard error (unbuffered, usually terminal)std::clog— standard error (buffered, usually terminal)
#include <iostream>
#include <string>
int main() {
int x;
std::string name;
// Read from stdin
std::cout << "Enter your name: ";
std::cin >> name;
std::cout << "Enter a number: ";
std::cin >> x;
// Write to stdout
std::cout << "Hello, " << name << "!\n";
std::cout << "You entered: " << x << "\n";
// Write to stderr
if (x < 0) {
std::cerr << "Warning: negative number\n";
}
}
File Streams
#include <fstream>
#include <iostream>
#include <string>
int main() {
// Write to a file
std::ofstream fout("output.txt");
if (!fout) {
std::cerr << "Failed to open file\n";
return 1;
}
fout << "Hello, World!\n";
fout << "The answer is: " << 42 << "\n";
fout.close();
// Read from a file
std::ifstream fin("output.txt");
if (!fin) {
std::cerr << "Failed to open file\n";
return 1;
}
std::string line;
while (std::getline(fin, line)) {
std::cout << "Read: " << line << "\n";
}
fin.close();
// Read and write (bidirectional)
std::fstream fio("data.txt", std::ios::in | std::ios::out | std::ios::trunc);
fio << "Initial data\n";
fio.seekg(0); // Go back to beginning
std::getline(fio, line);
std::cout << "Read back: " << line << "\n";
}
Common file open modes:
std::ios::in— open for readingstd::ios::out— open for writingstd::ios::app— append to endstd::ios::ate— seek to end after openingstd::ios::trunc— truncate file if it existsstd::ios::binary— binary mode (no text translation)
String Streams
#include <sstream>
#include <iostream>
#include <string>
int main() {
// Write to a string
std::ostringstream oss;
oss << "x = " << 42 << ", pi = " << 3.14159;
std::string result = oss.str();
std::cout << "Built string: " << result << "\n";
// Read from a string
std::istringstream iss("42 3.14 hello");
int x;
double y;
std::string word;
iss >> x >> y >> word;
std::cout << "Parsed: " << x << ", " << y << ", " << word << "\n";
// Bidirectional string stream
std::stringstream ss;
ss << "100 200";
int a, b;
ss >> a >> b;
std::cout << "Sum: " << (a + b) << "\n";
}
Stream Manipulators
#include <iostream>
#include <iomanip>
int main() {
// Formatting
std::cout << std::hex << 255 << "\n"; // ff
std::cout << std::oct << 255 << "\n"; // 377
std::cout << std::dec << 255 << "\n"; // 255
// Floating-point precision
std::cout << std::fixed << std::setprecision(2) << 3.14159 << "\n"; // 3.14
std::cout << std::scientific << 3.14159 << "\n"; // 3.14e+00
// Width and alignment
std::cout << "[" << std::setw(10) << std::left << "left" << "]\n";
std::cout << "[" << std::setw(10) << std::right << "right" << "]\n";
// Boolean
std::cout << std::boolalpha << true << "\n"; // true
std::cout << std::noboolalpha << true << "\n"; // 1
}
Appendices
For complete C++ iostream and iomanip references, see:
Key Takeaways
-
::fast_io::filebuf_fileowns astd::basic_filebuf*with RAII semantics. -
::fast_io::filebuf_io_observeris a non-owning view over an existingstd::basic_filebuf*, perfect for wrapping anfstream’srdbuf(). -
Only narrow (
filebuf_file) and wide (wfilebuf_file) variants exist, because the C++ standard library does not providebasic_filebuffor other character types. -
Sockets are just files. On POSIX systems, you can wrap a socket in a
filebuf_fileand usefstreamto read/write it. C++’s artificial separation of files and sockets (e.g., Boost.Asio vs fstream) violates the POSIX philosophy. -
C++ iostream has fundamental design flaws: pointer confusion (security
issues), not thread-safe, not exception-safe, stateful manipulators that corrupt stream
state, locale-dependent output, and poor performance.
fast_iofixes all of these. -
fast_io’s manipulators are stateless. Unlike
std::hexwhich changes the stream state,::fast_io::mnp::hex(value)applies only to that value. No state to restore, no bugs. -
Use fast_io internally for fstream implementations. If you need to
maintain compatibility with
fstream, use::fast_io::filebuf_io_observerinternally. The performance cost is minimal, and you get the benefits offast_io’s efficient syscall layer.