Program nyata jarang cukup mengandalkan data di dalam memorinya, karena banyak informasi justru datang dari berkas atau perlu disimpan ke berkas. Kelas File pada pustaka standar Ruby menyediakan pembacaan dan penulisan berkas teks dalam beberapa bentuk, mulai dari satu panggilan metode hingga pembukaan yang dikelola blok. Topik ini membahas File.read dan File.write, File.open dengan blok, pembacaan baris demi baris dengan each_line, serta pemeriksaan keberadaan dan penghapusan berkas. Seluruh contoh membuat berkasnya sendiri di direktori kerja sehingga dapat dijalankan berulang tanpa berkas tambahan dari luar.
Menulis dan membaca dengan File.write dan File.read#
File.write menerima nama berkas dan isinya berupa string, kemudian menulis isinya ke berkas tersebut. Pemanggilan ini menggunakan mode “w” secara bawaan, yaitu mode tulis yang menimpa seluruh isi lama apabila berkasnya sudah ada. Nilai kembalian metode ini berupa jumlah byte yang tertulis, sehingga keberhasilannya dapat diperiksa tanpa membuka berkas lagi. Metode ini juga menerima opsi mode:, sehingga File.write dengan mode: "a" menambahkan isi di akhir tanpa menghapus yang lama. Sebaliknya, File.read membaca seluruh isi sebuah berkas dan mengembalikannya sebagai satu string, termasuk karakter baris baru di dalamnya.
# menulis lalu membaca catatan suhu ruangan
File.write("suhu.txt", "Ruangan A, 24.5\nRuangan B, 27.0\n")
isi = File.read("suhu.txt")
puts isi
puts "Jumlah karakter: #{isi.size}"Ruangan A, 24.5
Ruangan B, 27.0
Jumlah karakter: 32Berkas di atas dijalankan dengan perintah ruby catatan-suhu.rb. Program menulis dua baris catatan ke suhu.txt, lalu membacanya kembali dan mencetak isi utuhnya. Hitungan 32 mencakup seluruh karakter isi berkas, termasuk karakter baris baru pada akhir setiap baris, karena File.read mengembalikan teks apa adanya. Pemanggilan File.write berikutnya dengan nama yang sama akan menggantikan isi ini secara penuh.
File.open dengan blok#
File.open membuka berkas dan menyerahkan objek IO, yaitu objek yang mewakili aliran data berkas, kepada blok yang menyertainya. Begitu blok selesai dijalankan, berkas ditutup secara otomatis, termasuk apabila error terjadi di dalam blok. Bentuk dengan blok menjadi cara yang disarankan karena penutupan tidak mungkin terlewat, sedangkan bentuk tanpa blok mengembalikan objek yang harus ditutup dengan close secara manual. Mode pembukaan dinyatakan pada argumen kedua, dan mode “a” membuka berkas untuk menambahkan isi di akhir tanpa menghapus isi lamanya. Nilai kembalian bentuk dengan blok adalah nilai terakhir di dalam blok tersebut, sehingga hasil pembacaan singkat dapat langsung ditampung.
# menambah baris pengukuran dengan mode "a"
File.write("log-suhu.txt", "08:00, 24.5\n")
File.open("log-suhu.txt", "a") do |berkas|
berkas.puts "12:00, 27.1"
end
puts File.read("log-suhu.txt")08:00, 24.5
12:00, 27.1Berkas di atas dijalankan dengan perintah ruby log-suhu.rb. Baris pertama program menyiapkan isi awal dengan File.write, kemudian File.open dengan mode “a” menambahkan satu pengukuran baru di akhir berkas. Pencetakan akhir menunjukkan kedua baris berdampingan, yang berarti isi lama tetap utuh. Metode puts pada objek berkas menulis ke berkas, bukan ke layar, karena metode itu dipanggil pada objek IO hasil pembukaan.
Membaca baris demi baris dengan each_line#
Hasil File.read berupa satu string utuh, sedangkan banyak pekerjaan justru memproses berkas per baris, misalnya menghitung rekap dari daftar pengukuran. Metode each_line pada objek berkas mengulangi isi berkas baris demi baris, dan setiap baris masih membawa karakter baris baru di bagian akhir. Baris yang berupa teks dikonversi menjadi bilangan dengan to_f sebelum dihitung. Alternatif dengan bentuk lebih ringkas adalah File.foreach, yang mengulangi baris berkas tanpa pembukaan eksplisit. Apabila teks baris akan digunakan apa adanya, karakter baris barunya dihapus dengan metode chomp.
# menghitung rata-rata suhu baris demi baris
File.write("pengukuran.txt", "24.5\n26.0\n25.5\n")
total = 0.0
jumlah = 0
File.open("pengukuran.txt") do |berkas|
berkas.each_line do |baris|
total += baris.to_f
jumlah += 1
end
end
puts "Jumlah pengukuran: #{jumlah}"
puts format("Rata-rata: %.1f", total / jumlah)Jumlah pengukuran: 3
Rata-rata: 25.3Berkas di atas dijalankan dengan perintah ruby rata-rata-suhu.rb. Pengulangan mengumpulkan tiga baris pengukuran, menjumlahkan nilai masing-masing setelah dikonversi menjadi bilangan desimal, lalu menghitung rata-ratanya. Karakter baris baru pada setiap baris tidak mengganggu konversi karena to_f hanya membaca bagian awal yang berupa angka. Pemrosesan per baris seperti ini juga hemat memori pada berkas besar karena setiap baris cukup ditampung satu per satu.
File.exist? dan File.delete#
File.exist? memeriksa keberadaan sebuah berkas dan mengembalikan true atau false, sedangkan File.delete menghapus berkas yang ditunjuk. Keduanya berpasangan pada pekerjaan arsip sederhana, misalnya membuat berkas sementara lalu membersihkannya setelah digunakan. Penghapusan terhadap berkas yang tidak ada membangkitkan error Errno::ENOENT, sehingga pemeriksaan File.exist? terlebih dahulu menghindarkan program dari kegagalan yang tidak perlu. Pemeriksaan ini juga bernilai true untuk direktori, sehingga berkas dan direktori dibedakan dengan File.file? dan File.directory?.
# memeriksa keberadaan berkas sebelum membaca dan menghapusnya
nama = "catatan-sementara.txt"
puts "#{nama} ada: #{File.exist?(nama)}"
File.write(nama, "Catatan ruangan A\n")
puts "#{nama} ada: #{File.exist?(nama)}"
File.delete(nama)
puts "#{nama} ada: #{File.exist?(nama)}"catatan-sementara.txt ada: false
catatan-sementara.txt ada: true
catatan-sementara.txt ada: falseBerkas di atas dijalankan dengan perintah ruby arsip-catatan.rb. Sebelum ditulis, berkas itu belum ada sehingga pemeriksaan pertama bernilai false. Setelah File.write membuatnya, pemeriksaan kedua bernilai true, kemudian File.delete menghapusnya dan pemeriksaan ketiga kembali bernilai false. Pola periksa sebelum bertindak ini berlaku pula sebelum membaca, yaitu memastikan berkasnya ada agar File.read tidak membangkitkan error.
Kesalahan umum#
Kesalahan pertama adalah membaca berkas yang belum ada tanpa penanganan apa pun. File.read membangkitkan Errno::ENOENT pada kasus itu, dan tanpa rescue programnya berhenti.
begin
puts File.read("arsip-tidak-ada.txt")
rescue Errno::ENOENT => e
puts "#{e.class}: #{e.message}"
endErrno::ENOENT: No such file or directory @ rb_sysopen - arsip-tidak-ada.txtPesan errornya menyebutkan nama berkas yang dicari. Perbaikannya berupa pemeriksaan File.exist? sebelum membaca atau penangkapan Errno::ENOENT apabila keberadaannya memang tidak pasti.
Kesalahan kedua adalah mengira File.write menambahkan isi di akhir. Mode bawaannya adalah “w” yang menimpa, sehingga pemanggilan berulang pada nama yang sama hanya menyisakan tulisan terakhir. Gunakan File.open dengan mode “a” untuk keperluan penambahan, atau bentuk File.write dengan mode: "a" yang memberikan hasil sama dalam satu panggilan.
Kesalahan ketiga adalah membuka berkas tanpa blok dan lupa memanggil close. Berkas yang dibiarkan terbuka menahan sumber daya sistem sampai program berakhir. Pilih bentuk File.open dengan blok agar penutupan terjadi otomatis, atau panggil close secara eksplisit pada jalur yang pasti dilalui.
Ringkasan#
File.writemenulis dengan mode “w” yang menimpa isi lama dan mengembalikan jumlah byte, sedangkanFile.readmengembalikan seluruh isi berkas sebagai satu string.File.opendengan blok menutup berkas secara otomatis setelah blok selesai, dan mode “a” menambahkan di akhir tanpa menghapus isi lama.each_linememproses berkas baris demi baris beserta karakter baris baru, sehingga cocok untuk rekap per baris.File.exist?memeriksa keberadaan sebelum membaca atau menghapus, sedangkanFile.deletemenghapus berkas dan gagal pada berkas yang tidak ada.
Referensi#
- File — Ruby — Dokumentasi kelas File beserta metode read, write, exist?, dan delete.
- IO — Ruby — Dokumentasi kelas IO sebagai induk operasi berkas, termasuk each_line dan penggunaan blok pada open.