Menu

File Handling di C: fopen, fclose, dan Membaca File Baris per Baris

Cara membaca dan menulis file di C: tabel mode fopen, memeriksa NULL, menulis dengan fprintf dan fputc, membaca dengan fgets, fscanf, dan fgetc, loop baris per baris yang standar, dan kapan memakai mode biner.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Semua yang dihitung sebuah program hilang saat program keluar, kecuali kalau ditulis ke suatu tempat. Antarmuka file di C ada di <stdio.h>, header yang sama dengan printf, dan sengaja dibuat mirip: file adalah stream berisi byte, dan fungsi-fungsi yang bekerja di layar punya kembaran yang menerima argumen stream.

Tipe handle-nya adalah FILE *. Kamu tidak pernah melihat isi FILE; tipe itu adalah tipe opaque (lihat typedef) dan kamu hanya pernah memegang pointer ke sana.

Tiga Langkahnya

Setiap operasi file mengikuti bentuk yang sama: buka, pakai, tutup.

Pemeriksaan NULL bukan sekadar kekhawatiran berlebihan. fopen gagal setiap kali file tidak ada (dalam mode baca), direktorinya tidak bisa ditulisi, path-nya salah, atau proses kehabisan handle file, dan semua itu mengembalikan NULL. Memakai handle NULL berujung segmentation fault.

Mengirim error ke stderr, bukan stdout, adalah konvensinya: stream itu tidak di-buffer, dan bisa diarahkan secara terpisah dari output yang sebenarnya.

Mode fopen

Argumen kedua adalah string mode yang pendek. Salah memilihnya adalah kesalahan paling merusak di seluruh area ini, karena "w" diam-diam mengosongkan file yang sudah ada.

ModeBacaTulisKalau file sudah adaKalau file belum ada
"r"yatidakdibuka dari awalgagal, mengembalikan NULL
"w"tidakyadikosongkandibuat
"a"tidakyahanya menulis di akhirdibuat
"r+"yayadibuka dari awalgagal, mengembalikan NULL
"w+"yayadikosongkandibuat
"a+"yayamembaca di mana saja, menulis di akhirdibuat

Tambahkan b ke salah satunya ("rb", "wb", "ab+") untuk mode biner; penjelasannya ada di bagian akhir.

Dua aturan yang mencegah kehilangan data sungguhan:

  • Gunakan "r" kalau kamu bermaksud membaca. "r+" pada nama file yang salah ketik gagal dengan aman; "w+" membuat file kosong dan yang hilang hanya waktumu. "w" pada nama file yang benar padahal maksudmu "r" akan menghancurkan datanya.
  • Gunakan "a" untuk log. Setiap fprintf mendarat di akhir file di mana pun posisi stream-nya, persis yang dibutuhkan log.

Editor di bawah menjalankan perjalanan pulang-pergi yang lengkap: membuat file, menulis data ke dalamnya, menutupnya, membukanya lagi untuk dibaca, lalu mencetak apa yang ditemukannya.

fprintf dan fscanf adalah printf dan scanf dengan stream sebagai argumen pertama; semua hal tentang format specifier-nya identik, termasuk lebar %31s yang mencegah name meluap.

Kondisi loop-nya adalah == 2, jumlah item yang diminta format. Menguji terhadap EOF adalah bug klasik: baris yang formatnya salah membuat fscanf mengembalikan 0, bukan EOF, dan loop berputar selamanya pada input yang tidak bisa diprosesnya.

Membaca Baris per Baris dengan fgets

fscanf praktis untuk data dengan format yang kaku. Untuk file teks, seperti konfigurasi, log, CSV, atau apa pun yang ditulis manusia, baca satu baris penuh. Loop ini adalah bentuk standarnya:

Yang membuat fgets menjadi pilihan default yang tepat:

  • Ia menerima ukuran buffer, jadi tidak bisa meluap. Berikan sizeof line dan pemanggilannya tetap benar kalau kamu mengubah ukuran array.
  • Ia mengembalikan NULL di akhir file atau saat error, yang menjadi kondisi loop yang rapi.
  • Ia mempertahankan karakter baris baru kalau barisnya muat di buffer. Itu berguna: tidak adanya '\n' di hasil yang kamu dapat berarti barisnya lebih panjang dari buffer-mu dan sisanya masih menunggu. strcspn(line, "\n") menemukan indeks karakter baris baru (atau panjang string kalau tidak ada), jadi meng-assign '\0' di sana memangkasnya dalam kedua kasus.

Untuk membedakan akhir file yang sebenarnya dari error, tanyakan setelah loop:

if (ferror(in)) {
    fprintf(stderr, "read error\n");
} else if (feof(in)) {
    /* normal end */
}

Jangan menulis while (!feof(fp)) sebagai kondisi loop. feof baru bernilai true setelah sebuah pembacaan gagal, jadi loop itu memproses isi buffer terakhir satu kali ekstra. Uji nilai kembalian fungsi pembacanya, seperti yang dilakukan kedua loop di atas.

Satu Karakter Sekali Baca: fgetc dan fputc

Untuk pekerjaan tingkat byte, seperti menghitung karakter, mengubah isi file, atau menyalin, fgetc dan fputc menangani satu karakter per pemanggilan.

Satu detail yang penting: c dideklarasikan sebagai int, bukan char. fgetc mengembalikan int agar bisa mengembalikan setiap nilai byte yang mungkin dan penanda khusus EOF (yang bernilai -1). Menyimpannya di char membuat perbandingan dengan EOF selalu false, atau keliru bernilai true untuk byte 0xFF, tergantung apakah char bersifat signed di platformmu. Ini salah satu jebakan tertua di C.

Memeriksa Error dengan Benar

Pembacaan di kode produksi terlihat seperti ini:

errno menyimpan kode yang menjelaskan kegagalan terakhir dan strerror mengubahnya menjadi kalimat; perror mencetak pesanmu ditambah kalimat itu dalam satu pemanggilan. Keduanya masing-masing butuh <errno.h> dan <string.h>.

fclose juga bisa gagal, karena ia mengosongkan data di buffer dan penulisannya mungkin tidak muat di disk. Jadi untuk hal yang penting, periksa:

if (fclose(fp) != 0) {
    fprintf(stderr, "failed to flush and close\n");
}

Mode Biner dalam Satu Paragraf

Mode teks bisa menerjemahkan akhir baris (di Windows, \n menjadi \r\n saat ditulis dan kembali lagi saat dibaca) dan bisa memperlakukan byte tertentu secara khusus. Untuk data yang bukan teks, seperti gambar, struct yang disalin apa adanya, atau blob terkompresi, buka dengan b dan gunakan fread/fwrite, yang memindahkan byte mentah:

fwrite(ptr, size, count, fp) menulis count item berukuran size byte dan mengembalikan berapa banyak yang berhasil ditulis; fread adalah cerminannya. Perlu diingat bahwa file yang ditulis dengan cara ini terikat pada mesin yang menulisnya: padding struct, ukuran integer, dan urutan byte semuanya ikut masuk ke byte-byte itu. Jadi cara ini cocok untuk cache atau file sementara, tetapi salah untuk format yang harus dibaca program lain.

Kesalahan Umum

  • Tidak memeriksa fopen terhadap NULL. Crash yang menyusul disalahkan pada pembacaan, bukan pada pembukaan file.
  • Membuka dengan "w" padahal maksudmu "r". File-nya sudah dikosongkan sebelum kamu sadar.
  • Lupa fclose. Output di buffer hilang, dan setiap file yang tidak ditutup membocorkan satu handle.
  • while (!feof(fp)). Memproses baris terakhir dua kali. Uji pemanggilan fungsi pembacanya.
  • char c = fgetc(fp). Merusak perbandingan dengan EOF. Gunakan int.
  • fscanf("%s", buf) tanpa lebar. Buffer overflow yang sama seperti scanf dari keyboard.
  • Path relatif. fopen("data.txt", "r") mencari di working directory, bukan di sebelah executable. Kalau sebuah file "menghilang", biasanya itulah sebabnya.

Pertanyaan yang sering diajukan

Bagaimana cara membuka file di C?

FILE *fp = fopen("data.txt", "r"); membuka file untuk dibaca dan mengembalikan handle FILE *, atau NULL kalau gagal. Selalu periksa NULL sebelum memakai handle itu, dan panggil fclose(fp) setelah selesai.

Apa saja mode fopen di C?

"r" untuk membaca (file harus sudah ada), "w" untuk menulis (membuat file baru, atau mengosongkan file yang sudah ada), "a" untuk menambahkan (membuat file baru, menulis di bagian akhir). Menambahkan + membuat masing-masing bisa membaca sekaligus menulis: "r+", "w+", "a+". Menambahkan b ("rb", "wb") membuka dalam mode biner.

Bagaimana cara membaca file baris per baris di C?

Gunakan fgets di dalam loop while: while (fgets(line, sizeof line, fp) != NULL) { ... }. Fungsi ini berhenti di setiap baris baru atau saat buffer penuh, mengembalikan NULL di akhir file, dan tidak bisa meluap karena kamu memberikan ukuran buffer-nya.

Kenapa file saya kosong setelah ditulis di C?

Paling sering karena kamu lupa fclose. Output disimpan di buffer, jadi data mungkin masih ada di memori saat program berhenti secara tidak normal. fclose mengosongkan buffer lalu menutup file; fflush(fp) mengosongkan buffer tanpa menutup. Penyebab lainnya adalah membuka dengan "w" untuk kedua kalinya, yang mengosongkan file yang baru saja kamu tulis.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai