Episode ini membahas streams dasar std::istream dan std::ostream, file I/O dengan std::ifstream, std::ofstream, dan std::fstream, formatted input output dengan manipulators, binary I/O, serta error handling dan pemeriksaan keberadaan file.

Program yang berguna hampir selalu membaca atau menulis data — dari keyboard, layar, file teks, hingga file biner. C++ mengemas semua ini dalam satu abstraksi: stream, yaitu aliran data berurutan yang tidak peduli apakah sumber atau tujuannya konsol atau disk.
Episode 9 membahas stream secara menyeluruh: dasar std::istream dan std::ostream, file I/O dengan std::ifstream dan std::ofstream, pemformatan output dengan manipulators, penyimpanan biner yang efisien, serta cara mendeteksi error saat operasi I/O gagal.
Semua operasi I/O C++ berjalan lewat stream. std::cout adalah ostream ke layar, std::cin adalah istream dari keyboard, std::cerr adalah ostream error ke stderr. Operator << menulis dan >> membaca:
cat > stream.cpp <<'EOF'
#include <iostream>
int main() {
int a = 5;
double b = 2.25;
std::cout << "Angka: " << a << " dan " << b << "\n";
std::cerr << "Ini pesan error\n";
int input;
std::cout << "Ketik angka: ";
std::cin >> input;
std::cout << "Kalian mengetik " << input << "\n";
}
EOF
g++ -std=c++20 stream.cpp -o stream
./streamstd::cout << a mengalirkan nilai a ke stream output. Stream bisa dirantai karena << mengembalikan stream yang sama. std::cerr dipakai untuk error karena tidak dibuffer dan muncul segera.
Operator >> berhenti di spasi. Untuk membaca satu baris penuh, gunakan std::getline — pola while (std::getline(std::cin, baris)) membaca baris dan berhenti saat input habis, karena getline mengembalikan stream yang bernilai false di akhir input.
std::ofstream menulis ke file, std::ifstream membaca dari file, dan std::fstream melakukan keduanya. File dibuka lewat constructor atau open, dan ditutup otomatis oleh RAII:
cat > file.cpp <<'EOF'
#include <iostream>
#include <fstream>
#include <string>
int main() {
std::ofstream out("data.txt");
out << "Baris pertama\n";
out << "Baris kedua\n";
out.close();
std::ifstream in("data.txt");
std::string baris;
while (std::getline(in, baris)) {
std::cout << baris << "\n";
}
}
EOF
g++ -std=c++20 file.cpp -o file
./file
cat data.txtstd::ofstream out("data.txt") membuka file untuk ditulis (dibuat bila belum ada). out.close() menutup secara eksplisit; jika tidak, destructor menutupnya. Membaca memakai pola yang sama dengan getline.
File bisa dibuka dengan mode tertentu lewat parameter kedua: std::ios::app untuk append, std::ios::trunc untuk menimpa, std::ios::binary untuk biner, dan std::ios::in atau std::ios::out untuk arah. Mode std::ios::app memastikan data baru ditambahkan di akhir file tanpa menghapus isi sebelumnya — penting untuk file log dan riwayat.
Manipulators mengubah cara stream menampilkan data tanpa mengubah nilai aslinya. std::setw mengatur lebar kolom, std::setprecision mengatur angka desimal, dan std::fixed memaksa notasi desimal tetap. Gabungan std::fixed << std::setprecision(2) menampilkan dua angka di belakang koma, dan std::setw(10) << std::right meratakan angka ke kanan dalam kolom selebar 10. Di C++20, std::format menawarkan cara yang lebih bersih.
File biner menyimpan data dalam bentuk aslinya tanpa konversi teks — lebih kompak dan lebih cepat untuk data numerik besar. Data ditulis byte per byte dengan write dan dibaca dengan read:
cat > biner.cpp <<'EOF'
#include <iostream>
#include <fstream>
int main() {
int data[3] = {10, 20, 30};
std::ofstream out("angka.bin", std::ios::binary);
out.write(reinterpret_cast<char*>(data), sizeof(data));
out.close();
int baca[3] = {0, 0, 0};
std::ifstream in("angka.bin", std::ios::binary);
in.read(reinterpret_cast<char*>(baca), sizeof(baca));
in.close();
std::cout << baca[0] << " " << baca[1] << " " << baca[2] << "\n";
}
EOF
g++ -std=c++20 biner.cpp -o biner
./binerout.write(reinterpret_cast<char*>(data), sizeof(data)) menulis seluruh array sebagai blok byte mentah. reinterpret_cast diperlukan karena write dan read bekerja pada char*. File biner tidak portabel antar platform dengan byte order berbeda — topik di episode 13.
Setiap stream menyimpan status: good(), fail(), eof(), dan bad(). Sebelum memproses file, periksa apakah pembukaan berhasil:
cat > cekfile.cpp <<'EOF'
#include <iostream>
#include <fstream>
int main() {
std::ifstream in("tidak-ada.txt");
if (!in) {
std::cerr << "Gagal membuka file\n";
return 1;
}
std::cout << "File terbuka\n";
}
EOF
g++ -std=c++20 cekfile.cpp -o cekfile
./cekfilePola if (!in) adalah idiom standar: bernilai true jika pembukaan gagal atau stream bermasalah. Selalu periksa status ini sebelum membaca.
Warning
Jangan memakai eof() sebagai kondisi perulangan. Kondisi while (!in.eof()) memproses data sekali terlalu banyak karena flag eof baru aktif setelah membaca melewati akhir file.
Inti yang harus dibawa pulang:
istream membaca, ostream menulis; dihubungkan operator >> dan <<.ifstream, ofstream, dan fstream menangani file teks dan biner.close eksplisit opsional.setw dan setprecision mengatur format tanpa mengubah nilai.write dan read untuk data mentah yang kompak.if (!stream) sebelum memproses file.Di episode 10 selanjutnya kita akan membahas templates dan generic programming — function templates dan class templates, template specialization dan variadic templates, concepts, type traits, dan SFINAE, serta std::optional dan std::variant untuk nilai yang mungkin kosong atau bertipe banyak.