Filehandle

Membuka filehandle dengan open bentuk tiga argumen, mode baca dan tulis, serta disiplin or die untuk kegagalan.

Daftar isi

Topik ini membahas filehandle, yaitu cara Perl mewakili hubungan antara program dan sebuah berkas sebelum berkas itu dibaca atau ditulis. Pembahasan dimulai dari konsep filehandle, fungsi open bentuk tiga argumen, tiga mode pembukaan baca dan tulis, disiplin or die untuk kegagalan, dan penutupan dengan close. Setelah seluruh contoh diikuti, berkas teks dapat dibuka, diisi, dibaca kembali, dan kegagalannya ditangani dengan pola yang digunakan program Perl sungguhan.

Mengenal filehandle#

Filehandle adalah variabel yang mewakili sebuah aliran data (stream) antara program dan sebuah berkas. Setelah berkas dibuka, seluruh pembacaan dan penulisan tidak dilakukan langsung pada nama berkasnya, melainkan melalui handle tersebut. Pola kerjanya selalu berurutan, yaitu membuka berkas dengan open, melakukan baca atau tulis melalui handle, kemudian melepaskannya dengan close.

Perl menyiapkan tiga filehandle sejak program dimulai tanpa perlu open. Handle STDIN mewakili masukan standar yang biasanya berasal dari papan ketik, STDOUT mewakili keluaran standar tempat print mengirim teksnya, dan STDERR mewakili saluran pesan error. Ketiganya sesungguhnya sudah digunakan sejak contoh pertama, karena setiap pernyataan print tanpa handle menulis ke STDOUT.

Filehandle modern ditulis dalam bentuk variabel leksikal, yaitu my $fh yang cakupannya terbatas pada blok tempat variabel itu dideklarasikan. Bentuk ini menggantikan gaya lama berupa nama tanpa tanda seperti FH yang berlaku global. Karena handle leksikal adalah variabel biasa, aturan use strict berlaku padanya, sehingga salah ketik nama handle langsung terdeteksi oleh interpreter. Dua gaya ini dapat hidup berdampingan pada satu program, tetapi bentuk leksikal menjadi pilihan baku pada kode modern karena cakupannya terkendali dan kesalahannya terdeteksi lebih awal.

Membuka berkas dengan open tiga argumen#

Fungsi open menghubungkan sebuah filehandle dengan berkas di penyimpanan. Bentuk yang digunakan pada kode modern terdiri atas tiga argumen, yaitu variabel handle, mode pembukaan, dan nama berkas. Argumen pertama ditulis dalam bentuk my $keluar langsung di dalam pemanggilan, sehingga deklarasi variabel dan pembukaan berkas terjadi pada satu pernyataan. Bila pembukaan berhasil, open mengembalikan nilai benar dan handle siap digunakan, sedangkan bila gagal, nilai kembaliannya salah dan disiplin or die menangani kegagalan itu.

Skrip berikut menulis tiga baris catatan suhu ke berkas baru, menutupnya, kemudian membuka berkas yang sama untuk dibaca dan menampilkan isinya:

perl tulis-catatan.pl
#!/usr/bin/perl
use strict;
use warnings;

# membuka berkas untuk ditulis, isi lama diganti seluruhnya
open(my $keluar, '>', 'catatan-suhu.txt')
    or die "Tidak dapat membuka catatan-suhu.txt: $!";

print $keluar "2024-05-06 07:00 suhu 24.1\n";
print $keluar "2024-05-06 08:00 suhu 25.3\n";
print $keluar "2024-05-06 09:00 suhu 27.0\n";

close($keluar);

# membuka berkas yang sama untuk dibaca
open(my $masuk, '<', 'catatan-suhu.txt')
    or die "Tidak dapat membuka catatan-suhu.txt: $!";

while (my $baris = <$masuk>) {
    chomp $baris;
    print "Tercatat: $baris\n";
}

close($masuk);
text Keluaran
Tercatat: 2024-05-06 07:00 suhu 24.1
Tercatat: 2024-05-06 08:00 suhu 25.3
Tercatat: 2024-05-06 09:00 suhu 27.0

Baris print $keluar "..." menunjukkan cara menulis melalui handle, yaitu print diikuti handle tanpa koma, lalu teks yang dikirim. Setelah tiga baris selesai ditulis, close($keluar) memutus hubungannya, dan berkas yang sama dibuka kembali dengan mode baca. Perulangan while pada contoh membaca berkas baris demi baris sampai akhir berkas tercapai, dan setiap barisnya ditampilkan dengan awalan Tercatat. Alur open, baca atau tulis, dan close ini adalah pola dasar seluruh operasi berkas di Perl.

openhubungkan berkasbaca atau tulismelalui filehandlecloselepas hubungan
Alur penggunaan filehandle dari open sampai close

Mode pembukaan berkas#

Argumen kedua open menentukan arah akses dan perilakunya terhadap isi lama. Tiga mode yang digunakan sehari-hari dirangkum pada tabel berikut.

ModeKegunaan
<Membuka berkas untuk dibaca, isi tidak diubah, dan gagal bila berkas tidak ada.
>Membuka berkas untuk ditulis, isi lama dihapus seluruhnya, dan berkas baru dibuat bila belum ada.
>>Membuka berkas untuk ditambah, isi lama dipertahankan, dan data baru diletakkan di bagian akhir.

Mode > selalu memulai dari berkas kosong, sehingga tepat digunakan untuk hasil olahan yang ditulis ulang dari awal pada setiap penjalanan. Mode >> mempertahankan isi lama dan menyambung data baru setelahnya, sehingga cocok untuk catatan yang bertambah secara berkala seperti log sensor. Skrip berikut menyiapkan isi awal berkas agar dapat dijalankan berulang kali, kemudian menambahkan dua baris baru dengan mode >> dan menampilkan seluruh isinya:

perl tambah-catatan.pl
#!/usr/bin/perl
use strict;
use warnings;

# menyiapkan isi awal berkas agar skrip dapat dijalankan berulang kali
open(my $awal, '>', 'catatan-suhu.txt')
    or die "Tidak dapat membuka catatan-suhu.txt: $!";

print $awal "2024-05-06 07:00 suhu 24.1\n";
print $awal "2024-05-06 08:00 suhu 25.3\n";
print $awal "2024-05-06 09:00 suhu 27.0\n";

close($awal);

# menambahkan dua baris baru tanpa menghapus isi lama
open(my $tambah, '>>', 'catatan-suhu.txt')
    or die "Tidak dapat membuka catatan-suhu.txt: $!";

print $tambah "2024-05-06 10:00 suhu 28.4\n";
print $tambah "2024-05-06 11:00 suhu 29.2\n";

close($tambah);

# menampilkan seluruh isi berkas setelah penambahan
open(my $masuk, '<', 'catatan-suhu.txt')
    or die "Tidak dapat membuka catatan-suhu.txt: $!";

while (my $baris = <$masuk>) {
    chomp $baris;
    print "$baris\n";
}

close($masuk);
text Keluaran
2024-05-06 07:00 suhu 24.1
2024-05-06 08:00 suhu 25.3
2024-05-06 09:00 suhu 27.0
2024-05-06 10:00 suhu 28.4
2024-05-06 11:00 suhu 29.2

Penanganan kegagalan dengan or die#

Pembukaan berkas dapat gagal karena banyak sebab, misalnya berkas tidak ada, izin baca tidak diberikan, atau jalurnya salah. Fungsi open melaporkan kegagalan dengan mengembalikan nilai salah, dan kelalaian memeriksa nilai tersebut berakibat fatal. Handle yang gagal tidak menunjuk berkas mana pun, sehingga pembacaan padanya tidak menghasilkan data dan penulisan yang dikirim padanya hilang tanpa satu pun pesan.

Disiplin or die menutup celah itu. Operator or mengevaluasi sisi kanannya hanya bila sisi kirinya salah, sehingga die dijalankan tepat ketika open gagal. Fungsi die mencetak pesan ke STDERR, mengakhiri program, dan memberikan kode keluar bukan nol kepada sistem operasi. Variabel khusus $! memuat pesan error dari sistem operasi, sehingga penyebab kegagalannya ikut tercetak. Skrip berikut sengaja membuka berkas yang tidak ada:

perl gagal-open.pl
#!/usr/bin/perl
use strict;
use warnings;

# berkas ini memang tidak ada, sehingga open gagal
open(my $fh, '<', 'laporan-hilang.txt')
    or die "Gagal membuka laporan-hilang.txt: $!\n";
text Keluaran
Gagal membuka laporan-hilang.txt: No such file or directory

Teks No such file or directory berasal dari $!, sehingga penyebab kegagalan langsung terbaca dari pesannya. Pesan pada contoh ditutup dengan \n, yaitu konvensi yang membuat die mencetak pesannya apa adanya. Tanpa baris baru pada akhirnya, die menambahkan letak kejadian berupa nama berkas skrip dan nomor baris tempat program berhenti, sehingga teks lengkapnya ikut bergantung pada tempat skrip dijalankan. Pola or die "$nama: $!\n" seperti pada contoh digunakan pada setiap open dalam topik ini dan sebaiknya diikuti tanpa kecuali.

Fungsi close melepaskan hubungan antara handle dan berkasnya. Penulisan pada Perl tidak selalu langsung mencapai penyimpanan, karena data sementara ditahan dalam buffer oleh sistem, dan close memastikan data yang tertahan itu benar-benar ditulis sebelum hubungannya diputus. Akibatnya, berkas yang baru selesai ditulis dapat dibaca kembali dengan aman setelah handle penulisnya ditutup, sebagaimana dilakukan pada kedua skrip di atas.

Setiap handle terbuka menggunakan satu slot pada tabel berkas sistem operasi, dan jumlah slot itu terbatas. Skrip yang membuka banyak berkas di dalam perulangan tanpa menutupnya dapat kehabisan slot sebelum pekerjaannya selesai. Program yang berakhir memang menutup handle yang masih terbuka secara otomatis, tetapi menutupnya segera setelah tugas selesai menjaga pemakaian sumber daya tetap kecil. Pemanggilan open berikutnya pada variabel handle yang sama memang menutup handle lamanya secara tidak langsung, tetapi mengandalkan perilaku itu membuat urutan penulisan sulit dilacak. Fungsi close mengembalikan nilai benar bila penutupan bersih dan nilai salah bila data terakhir gagal ditulis, sehingga program yang ketat juga memeriksa nilai kembaliannya.

Kesalahan umum#

Kesalahan pertama adalah mengabaikan nilai kembalian open. Handle yang gagal terlihat normal pada kode, tetapi data yang ditulis padanya lenyap tanpa pesan. Gejala yang muncul berupa berkas yang tetap kosong meskipun skrip tampak berjalan lancar, dan gejala itu sulit dihubungkan dengan penyebabnya. Perbaikannya mudah, yaitu menambahkan or die "$nama: $!\n" pada setiap pemanggilan open tanpa pengecualian.

Kesalahan kedua adalah menggunakan bentuk lama dengan handle bareword dan satu argumen:

perl Bentuk dua argumen yang tidak disarankan
# tidak-dijalankan
open(FH, $nama);

Pada bentuk ini, FH adalah nama global yang dapat tertukar dengan bagian program lain, dan tidak ada pemeriksaan kegagalan sama sekali. Bentuk seperti ini masih ditemukan pada banyak skrip lama, sehingga perlu dikenali ketika membacanya, tetapi tidak perlu ditiru pada skrip baru. Bentuk tiga argumen dengan variabel my menghilangkan kedua masalah sekaligus, sebagaimana digunakan pada seluruh contoh topik ini.

Kesalahan ketiga adalah salah memilih mode. Berkas yang hendak dibaca tetapi terbuka dengan > langsung dikosongkan pada saat itu juga, sebelum satu baris pun dibaca, sehingga isi aslinya tidak dapat dikembalikan. Arah akses perlu ditentukan lebih dahulu, yaitu baca dengan <, tulis ulang dengan >, atau sambung dengan >>.

Ringkasan#

  • open(my $fh, '<', $nama) or die "$nama: $!\n" membuka berkas dengan bentuk tiga argumen, dan setiap kegagalan ditangani dengan or die yang menampilkan isi $!.
  • Mode < membaca tanpa mengubah isi, mode > menulis dengan menghapus isi lama, dan mode >> menambah data di bagian akhir berkas.
  • Filehandle leksikal my $fh menggantikan handle bareword gaya lama dan mengikuti aturan use strict seperti variabel lain.
  • close($fh) memastikan data yang tertahan dalam buffer benar-benar ditulis dan melepaskan slot berkas sistem operasi.

Referensi#