Setiap pernyataan masukan dan keluaran Fortran tidak mengenali nama berkas secara langsung, melainkan bekerja pada unit, yaitu nomor logis yang terlebih dahulu dihubungkan ke sebuah berkas melalui pernyataan open. Topik ini membahas konsep unit beserta unit yang sudah terhubung sejak program dimulai, spesifikasi utama open dan close, penanganan berkas yang tidak ditemukan melalui iostat dan iomsg, serta pemeriksaan dan reposisi berkas dengan inquire, rewind, dan flush. Satu program utuh mendemonstrasikan seluruh mekanisme tersebut, mulai dari kegagalan membuka berkas yang tidak ada sampai pembacaan ulang baris pertama setelah reposisi, dan seluruh blok keluarannya adalah hasil eksekusi nyata dengan gfortran.
Unit sebagai perantara masukan dan keluaran#
Unit adalah nomor bilangan bulat yang menjadi perantara antara program dan sebuah berkas. Pernyataan read atau write menyebut nomor unit tersebut, bukan nama berkasnya, sehingga nama berkas hanya muncul satu kali pada pernyataan open. Beberapa unit sudah terhubung sejak program dimulai, biasanya unit 5 untuk masukan standar dan unit 6 untuk keluaran standar, tetapi cara paling aman adalah menggunakan konstanta output_unit, input_unit, dan error_unit dari modul intrinsik iso_fortran_env, sebagaimana dilakukan program contoh pada bagian berikutnya.
Nomor unit tidak perlu dipilih manual. Penanda newunit=unit pada pernyataan open meminta sistem waktu berjalan (runtime) memberikan nomor unit yang pasti belum terpakai, sehingga tabrakan nomor tidak terjadi. Unit yang terbuka tetap berlaku sampai ditutup dengan close atau sampai program berakhir, dan satu unit hanya boleh terhubung ke satu berkas pada satu waktu. Pola kerjanya selalu sama, yaitu membuka unit dengan open, mengolah data melalui read dan write, lalu menutupnya dengan close.
Membuka dan menutup dengan open dan close#
Pernyataan open menerima spesifikasi yang menyatakan sifat berkas yang diinginkan. Penanda file= menyebut namanya, status= menyatakan keadaan awalnya dengan nilai old untuk berkas yang harus sudah ada, new untuk berkas baru, replace untuk membuat baru dengan mengganti yang lama, dan scratch untuk berkas sementara. Penanda action= membatasi arah akses pada unit tersebut dengan nilai read, write, atau readwrite. Program berikut mencoba membuka berkas yang tidak ada, lalu mengelola berkas log hasil.txt sampai ke penutupannya.
program berkas_unit
use, intrinsic :: iso_fortran_env, only : output_unit, error_unit
implicit none
integer :: unit, unit_log
integer :: status
character(len=256) :: pesan
logical :: ada
integer :: ukuran
open (newunit=unit, file="tidak-ada.dat", status="old", action="read", &
iostat=status, iomsg=pesan)
if (status /= 0) then
write (error_unit, "(A, I0)") "open gagal, iostat = ", status
write (error_unit, "(A)") trim(pesan)
else
close (unit)
end if
open (newunit=unit_log, file="hasil.txt", status="replace", action="readwrite")
write (unit_log, "(A)") "catatan baris pertama"
write (unit_log, "(A)") "catatan baris kedua"
flush (unit_log)
inquire (unit=unit_log, opened=ada, size=ukuran)
write (output_unit, "(A, L1)") "Unit log masih terbuka : ", ada
write (output_unit, "(A, I0)") "Ukuran berkas hasil.txt : ", ukuran
rewind (unit_log)
read (unit_log, "(A)") pesan
write (output_unit, "(A)") "Setelah rewind : "//trim(pesan)
close (unit_log)
inquire (file="tidak-ada.dat", exist=ada)
write (output_unit, "(A, L1)") "tidak-ada.dat ditemukan : ", ada
end program berkas_unit# mengompilasi program dari direktori topik
gfortran berkas-unit.f90 -o berkas-unit
# menjalankan program
./berkas-unitopen gagal, iostat = 2
Cannot open file 'tidak-ada.dat': No such file or directory
Unit log masih terbuka : T
Ukuran berkas hasil.txt : 42
Setelah rewind : catatan baris pertama
tidak-ada.dat ditemukan : FDua baris pertama keluaran ditulis ke error_unit, yaitu arus kesalahan standar (standard error) yang pada terminal bercampur dengan keluaran biasa. Pembukaan tidak-ada.dat dengan status="old" gagal karena berkasnya memang tidak ada. Penanda iostat=status menangkap kode error 2 tanpa menghentikan program, sedangkan penanda iomsg=pesan mengisi variabel pesan dengan penyebab kegagalan sehingga program dapat melaporkan berkas mana yang tidak dapat dibuka. Bagian kedua program membuka hasil.txt dengan status="replace" dan action="readwrite", menulis dua baris ke dalamnya, dan unitnya dibiarkan terbuka untuk pembacaan ulang pada bagian berikutnya.
inquire, rewind, dan flush#
Pernyataan inquire memeriksa keadaan unit maupun berkas tanpa mengubah keduanya. Bentuk inquire (unit=unit_log, opened=ada, size=ukuran) mengisi ada dengan status keterbukaan unit dan ukuran dengan panjang berkas dalam byte, sehingga keluaran menampilkan T dan 42. Nilai 42 tersebut dapat dihitung dari isi berkasnya, yaitu dua baris masing-masing 21 dan 19 karakter ditambah satu byte penanda akhir baris pada setiap barisnya. Bentuk berdasarkan nama berkas, inquire (file="tidak-ada.dat", exist=ada), menguji keberadaan berkas pada disk sebelum program mencoba membukanya, dan keluarannya F sesuai kenyataan karena berkas itu memang tidak ada.
Pernyataan flush memaksa data yang masih berada di penyangga (buffer) ditulis benar-benar ke berkas, berguna agar berkas yang sedang ditulis bertahap sudah lengkap bila dibaca proses lain. Pernyataan rewind mengembalikan posisi pembacaan ke awal berkas, sehingga pernyataan read setelahnya membaca kembali baris pertama, sebagaimana terlihat pada keluaran Setelah rewind : catatan baris pertama. Untuk berpindah satu rekaman ke belakang tersedia pernyataan backspace, sedangkan penanda iostat pada read yang bernilai negatif menandai akhir berkas dan menjadi cara baku untuk menghentikan perulangan pembacaan.
Akses berurutan, langsung, dan stream#
Penanda access= pada open menentukan cara rekaman berkas diakses. Nilai bawaannya adalah sequential, yaitu berkas dibaca dan ditulis rekaman demi rekaman dari awal ke akhir, dan bentuk inilah yang digunakan seluruh contoh pada modul ini. Nilai direct membuka berkas akses langsung (direct access) dengan panjang rekaman tetap yang dinyatakan recl=, sehingga rekaman ke-n dapat dibaca atau ditulis tanpa melewati rekaman di depannya. Nilai stream menyediakan akses arus (stream access) yang memperlakukan berkas sebagai rangkaian byte dengan posisi bebas melalui pos=, cocok untuk berkas yang dibagikan dengan bahasa pemrograman lain.
Pilihan akses ini terpisah dari pilihan form= yang menentukan apakah rekamannya terformat atau tak terformat. Kombinasi yang paling lazim adalah sequential dengan form terformat untuk berkas teks, sedangkan kombinasi sequential dengan form tak terformat untuk data numerik berukuran besar dibahas pada topik rekaman terformat versus tak terformat di modul ini. Untuk pengolahan berkas besar yang aksesnya melompat-lompat, direct dan stream menghindarkan keharusan membaca ulang berkas dari awal.
Kesalahan umum#
Kesalahan pertama adalah membuka berkas masukan tanpa penanganan kegagalan. Program contoh pada topik ini sengaja menunjukkan pola yang benar, yaitu iostat=status diikuti pemeriksaan status /= 0 sebelum unit digunakan. Tanpa pola itu, berkas yang hilang atau izin yang kurang menghentikan program di tengah pekerjaan dengan pesan error waktu berjalan yang tidak dapat ditangani lebih lanjut oleh program.
Kesalahan kedua adalah menulis ke unit yang dibuka dengan action="read" atau sebaliknya membaca unit dengan action="write". Pelanggaran arah ini terdeteksi saat program berjalan sebagai error, bukan saat kompilasi, sehingga deklarasi action= perlu disesuaikan dengan penggunaan unitnya. Kesalahan ketiga adalah menganggap isi berkas sudah lengkap sebelum close atau flush dijalankan. Data yang masih berada di penyangga dapat hilang bila program berhenti secara tidak normal, sehingga untuk berkas yang ditulis bertahap, flush pada titik-titik penting menjaga isinya tetap konsisten.
Ringkasan#
- Unit adalah nomor logis perantara antara pernyataan IO dan berkas, diperoleh secara aman melalui
newunit=dan ditutup denganclose. openmenentukan nama, keadaan awal melaluistatus=, dan arah akses melaluiaction=, sedangkaniostatdaniomsgmenangkap kegagalan pembukaan tanpa menghentikan program.inquirememeriksa status unit, ukuran berkas, dan keberadaan berkas,rewindmengembalikan posisi ke awal, danflushmemaksa penyangga ditulis ke berkas.- Penanda
access=memilih akses berurutan, langsung denganrecl=, atau stream dengan posisi byte bebas.
Referensi#
- Learn: tutorial resmi Fortran — fortran-lang — Kumpulan tutorial resmi komunitas Fortran yang mencontohkan penggunaan open, read, dan write pada berkas.
- The GNU Fortran Compiler — GNU Project — Manual gfortran yang menjadi rujukan perilaku open, inquire, dan pesan error pembukaan berkas pada contoh topik ini.