Topik ini membahas pembacaan dan penulisan berkas di C++ melalui tiga kelas file stream, yaitu std::ofstream untuk menulis, std::ifstream untuk membaca, dan std::fstream untuk keduanya. Pembahasan mencakup cara membuka berkas beserta mode pembukaannya (open mode), kebiasaan memeriksa kegagalan sejak awal, dan pola menulis lalu membaca kembali satu berkas dalam satu program. Semua contoh membuat berkasnya sendiri, sehingga keluarannya dapat direproduksi tanpa menyiapkan berkas pendamping.
Menulis berkas dengan ofstream#
std::ofstream adalah stream keluaran yang tujuannya berkas. Konstruktor kelas ini langsung membuka berkas yang namanya diberikan, sehingga penulisan dapat dimulai segera dengan operator <<, sama seperti mencetak ke std::cout. Sebelum stream dipakai menulis, keberhasilan pembukaannya wajib diperiksa. Objek std::ofstream dapat diuji langsung dalam kondisi if, dan uji tersebut bernilai false apabila berkas tidak berhasil dibuka.
Program berikut menyimpan catatan sensor suhu ke berkas sensor.log, lalu membaca kembali isinya dengan std::getline. Perhatikan pemanggilan keluar.close() sebelum berkas dibaca. Data yang ditulis lewat << pertama-tama ditampung di buffer, yaitu memori perantara, dan belum tentu sampai ke berkas sebelum stream ditutup atau di-flush.
#include <fstream>
#include <iostream>
#include <string>
int main() {
// tulis catatan sensor suhu ke berkas teks
std::ofstream keluar("sensor.log");
if (!keluar) {
std::cerr << "Error: berkas sensor.log tidak bisa dibuat.\n";
return 1;
}
keluar << "07:00 22.5\n";
keluar << "08:00 23.1\n";
keluar << "09:00 24.8\n";
keluar.close(); // tutup agar semua data benar-benar tertulis
// baca kembali isi berkas baris demi baris
std::ifstream masuk("sensor.log");
if (!masuk) {
std::cerr << "Error: berkas sensor.log tidak bisa dibuka.\n";
return 1;
}
std::string baris;
int nomor = 0;
while (std::getline(masuk, baris)) {
++nomor;
std::cout << nomor << ": " << baris << "\n";
}
return 0;
}1: 07:00 22.5
2: 08:00 23.1
3: 09:00 24.8Pemanggilan close() memaksa seluruh isi buffer benar-benar tertulis ke berkas sebelum pembacaan dimulai. Tanpa pemanggilan itu, data baru tersimpan ketika objek keluar mengakhiri masa hidupnya di akhir main, sehingga pembacaan di tengah program dapat menemukan berkas yang masih kosong. Penutupan otomatis pada akhir masa hidup objek adalah penerapan prinsip RAII, sehingga berkas selalu tertutup bahkan apabila fungsi berakhir lebih dahulu melalui return.
Membaca berkas dengan ifstream#
std::ifstream adalah stream masukan yang sumbernya berkas. Isi berkas dapat dibaca dengan operator >> untuk data berformat atau dengan std::getline untuk baris utuh, dan pembacaan baris demi baris menjadi pola paling umum untuk berkas teks. Perulangan while (std::getline(masuk, baris)) berjalan selama masih ada baris dan berhenti secara otomatis di akhir berkas.
Pembukaan berkas yang tidak ada tidak melempar exception. Konstruktor std::ifstream melaporkan kegagalan melalui keadaan stream, sehingga pemeriksaan if (!masuk) setelah deklarasi menjadi kebiasaan yang wajib. Program berikut mencoba membaca arsip yang memang tidak tersedia, lalu menangani kegagalannya dengan percabangan.
#include <fstream>
#include <iostream>
int main() {
std::ifstream masuk("arsip-tidak-ada.txt");
if (!masuk) {
std::cerr << "Error: arsip-tidak-ada.txt tidak dapat dibuka.\n";
return 1;
}
// bagian ini tidak pernah dijalankan karena pembukaan selalu gagal
std::string baris;
while (std::getline(masuk, baris)) {
std::cout << baris << "\n";
}
return 0;
}Error: arsip-tidak-ada.txt tidak dapat dibuka.Pesan error dilaporkan melalui std::cerr, sedangkan return 1 mengakhiri program dengan kode keluar selain nol agar script shell dapat mendeteksinya. Kegagalan yang disengaja seperti ini berulang secara deterministik, karena berkas arsip-tidak-ada.txt memang tidak pernah dibuat dan pesan yang sama selalu muncul pada setiap eksekusi.
Selain pengujian kondisi, keberhasilan pembukaan dapat diperiksa dengan is_open(), yang bernilai true apabila berkas sudah terhubung ke stream. Kedua cara itu setara untuk kebutuhan umum, dan pengujian kondisi lebih ringkas sehingga lebih sering dipakai. Ketika berkas berhasil dibuka tetapi isinya habis, std::getline langsung gagal dan perulangan tidak dijalankan sama sekali, sedangkan baris kosong di tengah berkas tetap terbaca sebagai string kosong.
Mode open dan std::fstream#
Ketiga kelas menerima argumen kedua berupa mode open, yaitu sekumpulan konstanta dari std::ios yang menentukan cara berkas dibuka. Mode dapat digabung dengan operator |. Tanpa argumen kedua, std::ofstream membuka berkas untuk menulis, std::ifstream untuk membaca, sedangkan std::fstream untuk keduanya pada objek yang sama.
| Mode | Efek |
|---|---|
std::ios::in | membuka berkas untuk dibaca, posisi awal di awal berkas |
std::ios::out | membuka berkas untuk ditulis |
std::ios::app | setiap penulisan ditempatkan di akhir berkas |
std::ios::ate | posisi awal dipindah ke akhir berkas, tetapi posisi dapat berpindah lagi |
std::ios::trunc | isi berkas yang sudah ada dihapus sejak awal |
std::ios::binary | data dibaca dan ditulis apa adanya, tanpa penanganan karakter khusus |
Kombinasi yang paling sering dipakai selain mode bawaan adalah std::ios::app untuk menambah data di akhir berkas tanpa menghapus isinya, misalnya pada log yang terus bertambah. Apabila berkas yang sama juga perlu dibaca, std::fstream menjadi pilihan tepat karena pembacaan dan penulisan dilakukan pada satu objek yang sama.
// tidak-dijalankan (fragmen mode open, bukan program utuh)
std::fstream arsip("cadangan.log", std::ios::out | std::ios::app);
arsip << "2026-11-02 10:00 25.3\n";Mode std::ios::ate berbeda dengan std::ios::app dalam satu hal penting. Mode ate hanya memindahkan posisi awal ke akhir berkas, dan posisi itu tetap boleh berpindah kembali. Mode app mengunci setiap penulisan agar selalu ditempatkan di akhir berkas. Adapun mode std::ios::binary mematikan penanganan karakter khusus dan dibahas lebih lanjut pada topik I/O teks versus biner. Tanpa argumen mode, std::fstream menggunakan gabungan std::ios::in dan std::ios::out, sehingga berkasnya wajib sudah ada karena mode in tidak menciptakan berkas baru.
Kesalahan umum#
Kekeliruan berikut paling sering muncul saat program mulai bekerja dengan berkas.
- Membaca ulang berkas tanpa menutup stream penulisnya terlebih dahulu. Data masih tertahan di buffer, sehingga pembacaan menemukan berkas yang kosong atau isinya parsial. Perbaikannya memanggil
close()sebelum stream pembaca dibuka. - Mengabaikan hasil pembukaan. Konstruktor tidak melempar exception, sehingga program tanpa pemeriksaan terus berjalan dengan stream yang tidak terhubung ke berkas apa pun. Perbaikannya menguji kondisi stream segera setelah deklarasi.
- Memakai
std::ofstreambiasa untuk menambah data. Setiap pembukaan menghapus isi lama. Perbaikannya menambahkanstd::ios::apppada argumen mode pembukaannya. - Membaca rekaman biner dengan
std::getline. Pembacaan mengikuti karakter baris baru, bukan batas rekaman, sehingga hasilnya tidak terstruktur. Perbaikannya membaca denganread()sebagaimana dibahas pada topik I/O teks versus biner.
Ringkasan#
std::ofstreammenulis danstd::ifstreammembaca, sedangkanstd::fstreammenangani keduanya pada satu objek.- Keberhasilan pembukaan diperiksa dengan menguji kondisi stream, karena konstruktor melaporkan kegagalan melalui keadaan stream, bukan exception.
- Penulisan lewat
<<tertahan di buffer sampai stream ditutup atau di-flush, sehingga pembacaan ulang harus menunggu setelahclose(). - Mode open seperti
std::ios::app,std::ios::ate, danstd::ios::binarymengubah perilaku pembukaan, sedangkanstd::ios::outsaja mengosongkan berkas lama.
Referensi#
- std::basic_fstream — cppreference — Dokumentasi kelas stream berkas yang dapat membaca dan menulis.
- std::basic_ofstream — cppreference — Dokumentasi stream keluaran berkas beserta mode pembukaannya.
- std::basic_ifstream — cppreference — Dokumentasi stream masukan berkas.
- std::ios_base::openmode — cppreference — Daftar konstanta mode pembukaan berkas.
- Basic file I/O — LearnCpp — Pembahasan dasar membaca dan menulis berkas dengan fstream.