Setiap pernyataan write ke berkas menghasilkan satu rekaman (record), dan bentuk rekaman itu ditentukan oleh penanda form= pada pernyataan open. Rekaman terformat (formatted) menyimpan setiap nilai sebagai teks yang mengikuti spesifikasi format, sedangkan rekaman tak terformat (unformatted) menyalin representasi memori nilai apa adanya. Topik ini membandingkan keduanya pada data numerik yang sama, mencakup ukuran berkas hasilnya, kecepatan dan ketepatan pembacaan kembali, serta penanda rekaman yang mengapit data pada berkas tak terformat. Satu program menulis seribu nilai real ke kedua bentuk berkas, membacanya kembali, dan membandingkan ukurannya, dengan seluruh keluaran diambil dari eksekusi nyata gfortran.
Rekaman terformat: setiap nilai menjadi teks#
Pada berkas terformat, setiap nilai diubah menjadi rangkaian karakter sesuai deskriptor format sebagaimana dibahas pada topik deskriptor edit format. Program berikut menulis seribu nilai 0.1 * i satu per satu dengan deskriptor E24.14, sehingga setiap rekaman berisi satu nilai dalam notasi eksponensial berlebar 24 karakter. Hasilnya adalah berkas teks yang dapat dibuka dengan editor mana pun, dapat diperiksa isinya secara langsung, dan tetap dapat dibaca program lain tanpa mengetahui bahasa pemrograman yang menulisnya.
Sifat portabel tersebut menjadi kekuatan utama rekaman terformat. Isinya tidak bergantung pada representasi internal komputer karena setiap nilai sudah menjadi teks, sehingga berkas yang ditulis di satu mesin dapat dibaca di mesin lain dengan kompiler berbeda. Harga yang dibayar adalah ukuran berkas dan waktu proses, karena setiap nilai real presisi tunggal memerlukan sekitar dua puluh karakter padahal di memori nilainya hanya membutuhkan empat byte, dan konversi teks harus dilakukan dua arah saat menulis dan saat membaca.
Rekaman tak terformat: representasi memori apa adanya#
Pada berkas tak terformat, penanda form="unformatted" menyatakan bahwa write menyalin byte internal nilai tanpa konversi ke teks. Seribu nilai real presisi tunggal ditulis dengan satu pernyataan write (unit) data_uji tanpa perulangan elemen satu per satu, dan hasilnya berukuran jauh lebih kecil karena setiap nilai hanya membutuhkan empat byte. Penulisan dan pembacaannya juga lebih cepat karena tidak ada pengubahan format sama sekali, sehingga bentuk ini menjadi pilihan lazim untuk berkas antara (intermediate file) dan data numerik berukuran besar pada perhitungan ilmiah.
Konsekuensinya ada pada keterbacaan dan portabilitas. Isi berkasnya tidak dapat dibaca manusia, dan representasi internalnya bergantung pada arsitektur, termasuk urutan byte (endianness) dan panjang penanda rekaman yang mengapit datanya. Program contoh pada bagian berikutnya menulis dan membaca kedua bentuk berkas pada mesin yang sama, sehingga perbandingan ukuran dan ketepatan keduanya dapat diamati langsung dari keluarannya.
Program perbandingan dan keluarannya#
program terformat_biner
implicit none
integer, parameter :: n = 1000
real :: data_uji(n)
real :: baca_terformat(n)
real :: baca_biner(n)
integer :: unit
integer :: i
integer :: ukuran_teks
integer :: ukuran_biner
do i = 1, n
data_uji(i) = 0.1 * real(i)
end do
! rekaman terformat: setiap nilai diubah menjadi teks
open (newunit=unit, file="data-terformat.txt", status="replace", action="write")
do i = 1, n
write (unit, "(E24.14)") data_uji(i)
end do
close (unit)
! rekaman tak terformat: representasi memori ditulis apa adanya
open (newunit=unit, file="data-biner.bin", form="unformatted", status="replace", &
action="write")
write (unit) data_uji
close (unit)
! membaca kembali kedua berkas dan memverifikasi isinya
open (newunit=unit, file="data-terformat.txt", status="old", action="read")
do i = 1, n
read (unit, "(E24.14)") baca_terformat(i)
end do
close (unit)
open (newunit=unit, file="data-biner.bin", form="unformatted", status="old", &
action="read")
read (unit) baca_biner
close (unit)
print *, "Elemen 1 :", data_uji(1), baca_terformat(1), baca_biner(1)
print *, "Elemen 1000 :", data_uji(n), baca_terformat(n), baca_biner(n)
print *, "Selisih maksimum terformat :", maxval(abs(data_uji - baca_terformat))
print *, "Selisih maksimum biner :", maxval(abs(data_uji - baca_biner))
! membandingkan ukuran kedua berkas hasil penulisan
inquire (file="data-terformat.txt", size=ukuran_teks)
inquire (file="data-biner.bin", size=ukuran_biner)
print *, "Ukuran berkas terformat (byte) :", ukuran_teks
print *, "Ukuran berkas biner (byte) :", ukuran_biner
end program terformat_biner# mengompilasi program dari direktori topik
gfortran terformat.f90 -o terformat
# menjalankan program
./terformat Elemen 1 : 0.100000001 0.100000001 0.100000001
Elemen 1000 : 100.000000 100.000000 100.000000
Selisih maksimum terformat : 0.00000000
Selisih maksimum biner : 0.00000000
Ukuran berkas terformat (byte) : 25000
Ukuran berkas biner (byte) : 4008Keluaran memperlihatkan bahwa kedua jalur pembacaan kembali menghasilkan nilai yang identik dengan nilai asalnya, ditandai selisih maksimum nol pada keduanya. Ketepatan jalur terformat bukan kebetulan, karena deskriptor E24.14 mencetak empat belas angka di belakang titik, sedangkan real presisi tunggal hanya menyimpan sekitar sembilan angka signifikan, sehingga tidak ada informasi yang hilang ketika nilai ditulis dan dibaca kembali. Bila deskriptornya disempit, misalnya E12.4, jalur terformat justru kehilangan ketepatan, sedangkan jalur tak terformat tetap utuh karena nilainya tidak pernah dikonversi ke teks.
Perbedaan ukurannya mencolok, yaitu 25000 byte berbanding 4008 byte untuk data yang sama. Berkas terformat membutuhkan 25 byte per rekaman, yakni 24 karakter medan E24.14 ditambah satu penanda akhir baris, sedangkan berkas tak terformat menyimpan seribu nilai menjadi 4000 byte data. Sisa 8 byte pada berkas biner berasal dari penanda pembuka dan penutup rekaman yang dijelaskan pada bagian berikutnya.
Penanda rekaman dan perhitungan ukuran#
Berkas tak terformat akses berurutan menyisipkan penanda rekaman (record marker) di awal dan akhir setiap rekaman, yaitu bilangan bulat yang menyatakan panjang rekamannya. Perintah berikut menampilkan dua baris pertama berkas terformat dan 16 byte pertama berkas biner hasil program di atas untuk membuktikan strukturnya.
# menampilkan dua baris pertama berkas terformat
head -2 data-terformat.txt
# menampilkan 16 byte pertama berkas tak terformat
od -A d -t x1 -N 16 data-biner.bin 0.10000000149012E+00
0.20000000298023E+00
0000000 a0 0f 00 00 cd cc cc 3d cd cc 4c 3e 9a 99 99 3e
0000016Empat byte pertama berkas biner terbaca a0 0f 00 00, yang dalam urutan byte kecil (little-endian) bernilai 4000, tepat sebesar 1000 elemen dikali 4 byte. Nilai inilah yang ditulis oleh penanda pembuka rekaman gfortran, dan penanda penutup yang senilai dengannya menyusul di akhir rekaman sehingga total berkas menjadi 4008 byte. Empat byte berikutnya, cd cc cc 3d, adalah representasi memori 0.1 dalam real presisi tunggal, diikuti cd cc 4c 3e untuk 0.2. Sementara itu, dua baris pertama berkas terformat menunjukkan nilai yang sama dalam bentuk teks 0.10000000149012E+00 berlebar 24 karakter. Perbandingan ini memperlihatkan perbedaan ukuran per nilai, yaitu 4 byte memori berbanding 25 byte teks per rekaman.
Struktur penanda ini sekaligus menjelaskan mengapa berkas tak terformat tidak portabel lintas kompiler. Panjang penandanya ditentukan implementasi, dan penanda tersebut membuat read tanpa format dapat memverifikasi panjang rekaman yang dibaca. Berkasnya hanya dijamin terbaca kembali oleh kompiler yang sama pada arsitektur yang sama, sedangkan pertukaran berkas antar mesin memerlukan konversi eksplisit.
Kapan memilih rekaman tak terformat#
Tabel berikut merangkum pertimbangan pemilihan bentuk rekaman untuk data numerik.
| Aspek | Terformat | Tak terformat |
|---|---|---|
| Keterbacaan manusia | Dapat dibaca dan disunting editor teks | Tidak dapat dibaca manusia |
| Ukuran berkas | Besar, sekitar 25 byte per real presisi tunggal pada contoh ini | Kecil, 4 byte per real presisi tunggal |
| Kecepatan | Lebih lambat karena konversi teks dua arah | Lebih cepat karena penyalinan memori |
| Ketepatan | Bergantung pada jumlah digit deskriptor | Identik dengan nilai di memori |
| Portabilitas | Aman lintas mesin dan kompiler | Terikat kompiler dan arsitektur yang sama |
Pilihan yang lazim adalah rekaman terformat untuk hasil akhir yang dibaca manusia atau dibagikan ke program lain, sedangkan rekaman tak terformat untuk berkas antara (intermediate file) antartahap perhitungan dan arsip data berukuran besar yang hanya dibaca kembali oleh program yang sama. Program ilmiah berukuran besar umumnya menggunakan keduanya sekaligus, yaitu data mentah ditulis tak terformat demi kecepatan, lalu ringkasannya ditulis terformat demi keterbacaan.
Kesalahan umum#
Kesalahan pertama adalah membaca berkas tak terformat dengan pernyataan terformat atau sebaliknya. Struktur rekamannya berbeda sehingga pembacaan berakhir dengan error atau menghasilkan nilai yang tidak bermakna, dan penyebabnya sering kali berupa kelalaian menuliskan form="unformatted" pada open saat membaca berkas tak terformat. Pastikan nilai form= pada pernyataan open pembaca sama dengan pernyataan penulisnya.
Kesalahan kedua adalah menganggap berkas tak terformat portabel. Urutan byte berbeda antar arsitektur, dan panjang penanda rekaman berbeda antar kompiler, sehingga berkas yang dipindahkan antar mesin perlu dikonversi terlebih dahulu. Kesalahan ketiga adalah mempercayai deskriptor terformat yang sempit. Bila deskriptor E12.4 digunakan pada data serupa, sebagian angka signifikan hilang karena pembulatan sehingga selisih maksimum pada keluaran program tidak lagi nol. Aturan praktisnya adalah memeriksa ketepatan tulis-baca ulang dengan membandingkan nilai asal dan nilai bacaan, persis seperti yang dilakukan program contoh pada topik ini.
Ringkasan#
- Rekaman terformat menyimpan nilai sebagai teks sesuai deskriptor sehingga portabel, sedangkan rekaman tak terformat menyalin representasi memori sehingga ringkas dan cepat.
- Pada contoh seribu real presisi tunggal, berkas terformat berukuran 25000 byte dan berkas tak terformat 4008 byte, dengan selisih pembacaan nol pada keduanya karena
E24.14memuat lebih banyak digit daripada yang disimpan real presisi tunggal. - Berkas tak terformat akses berurutan diapit penanda rekaman berisi panjang rekaman, pada gfortran berukuran 4 byte, sehingga 4000 byte data menjadi 4008 byte berkas.
- Rekaman tak terformat hanya portabel pada kompiler dan arsitektur yang sama, sedangkan rekaman terformat aman dipindahkan antar mesin.
Referensi#
- Learn: tutorial resmi Fortran — fortran-lang — Kumpulan tutorial resmi komunitas Fortran yang mencontohkan penulisan berkas terformat dan tak terformat.
- The GNU Fortran Compiler — GNU Project — Manual gfortran yang menjadi rujukan bentuk rekaman unformatted dan penanda rekaman pada kompiler contoh topik ini.