Pustaka io dan os

I/O berkas, fungsi os.time dan os.date, serta batasan pustaka pada lingkungan tersemat.

Daftar isi

Pustaka io mengatur pembacaan dan penulisan berkas, sedangkan pustaka os menyediakan akses ke waktu sistem, lingkungan, dan nama berkas. Topik ini membahas io.open dengan mode w, a, dan r, metode read, lines, dan close, perbedaan io.write dengan print, serta os.time, os.date, os.rename, dan os.remove. Setiap contoh membuat berkas latihannya sendiri di direktori tempat skrip dijalankan, sehingga berkas tersebut muncul sebentar lalu dihapus dan keluarannya dapat direproduksi. Bahasan ditutup dengan batasan kedua pustaka pada lingkungan tersemat, tempat Lua sering tidak diizinkan menyentuh berkas.

Fungsi io.open(nama, mode) membuka berkas dan mengembalikan objek berkas (file handle), yaitu perwakilan berkas yang menyimpan posisi baca dan tulis. Mode w membuka berkas untuk ditulis dari awal dan mengosongkan isi lama, mode a menambahkan di akhir, sedangkan mode r membuka untuk dibaca. Metode write menulis apa adanya tanpa pemindah baris, metode lines mengulang baris demi baris, dan close menutup berkas. Skrip berikut menulis dua catatan, menambahkan satu catatan, lalu membaca seluruh isinya kembali.

lua arsip-catatan.lua
-- Menulis, menambah, dan membaca berkas arsip catatan
local f = io.open("arsip-catatan.txt", "w")
f:write("Catatan pertama\n")
f:write("Catatan kedua\n")
f:close()

f = io.open("arsip-catatan.txt", "a")
f:write("Catatan tambahan\n")
f:close()

f = io.open("arsip-catatan.txt", "r")
for baris in f:lines() do
  print(baris)
end
f:close()

os.remove("arsip-catatan.txt")
text Keluaran
Catatan pertama
Catatan kedua
Catatan tambahan

Berkas arsip-catatan.txt tercipta di direktori tempat skrip dijalankan, tumbuh dengan mode a, lalu dibaca kembali baris demi baris sebelum dihapus oleh os.remove. Perulangan for baris in f:lines() menghasilkan baris tanpa pemindah baris, sehingga print cukup memanggilnya satu per satu. Skrip yang sama juga memperlihatkan bahwa objek berkas ditutup sebelum dibuka kembali dengan mode yang berbeda.

Apabila berkas yang diminta tidak ada, io.open tidak memunculkan error, melainkan mengembalikan nil beserta pesan error. Bentuk ini menjadikan pola pemeriksaan local f, err = io.open(nama, mode) sebagai langkah pembuka yang aman sebelum metode apa pun dipanggil.

lua Contoh: io.open yang gagal mengembalikan nil
local f, err = io.open("tidak-ada.txt", "r")
print(f)
print(err)
text Keluaran
nil
tidak-ada.txt: No such file or directory

Nilai nil pada baris pertama adalah objek berkas yang gagal dibuat, sedangkan baris kedua menampilkan penyebabnya dari sistem operasi. Pemeriksaan sederhana seperti if f == nil then sudah cukup untuk menahan error berikutnya.

Tiga mode pembacaan read#

Metode read menerima string mode yang menentukan bentuk hasilnya. Mode "l" membaca satu baris tanpa pemindah baris, mode "L" membaca satu baris beserta pemindah barisnya, sedangkan mode "a" membaca seluruh sisa isi berkas. Perbedaan l dan L tampak kecil, tetapi menentukan apakah hasil pembacaan menyatu dengan baris berikutnya. Skrip berikut membuat berkas latihannya sendiri, membacanya dengan ketiga mode, lalu menghapus berkasnya.

lua Contoh: tiga mode pembacaan read
-- Berkas latihan dibuat sendiri oleh skrip ini
local f = io.open("mode-baca.txt", "w")
f:write("baris satu\n", "baris dua\n")
f:close()

f = io.open("mode-baca.txt", "r")
local a = f:read("l")
local b = f:read("L")
local c = f:read("a")
print("read l : '" .. a .. "'")
print("read L : '" .. b .. "'")
print("read a : '" .. c .. "'")
f:close()

os.remove("mode-baca.txt")
text Keluaran
read l : 'baris satu'
read L : 'baris dua
'
read a : ''

Keluaran memperlihatkan perbedaannya secara langsung. Hasil read("l") bersih dari pemindah baris, sedangkan hasil read("L") membawa pemindah baris sehingga penutup kutip tercetak pada baris sendiri. Hasil read("a") berupa string kosong karena kedua baris sudah habis dibaca, dan perubahan panjang hasil inilah yang biasa digunakan untuk menandai akhir berkas.

io.write tanpa pemindah baris otomatis#

Fungsi print menambahkan pemindah baris di akhir dan pemisah TAB di antara argumen, sedangkan io.write menulis apa adanya tanpa menambahkan apa pun. Karakteristik ini membuat io.write tepat untuk menyusun satu baris dari beberapa potongan, misalnya label dan angka pada baris log sensor. Angka yang ditulis io.write diformat secara bawaan, sehingga 28.5 tetap tercetak 28.5.

lua Contoh: io.write tanpa pemindah baris otomatis
io.write("Sensor 01: ")
io.write(28.5, " derajat C")
io.write("\n")
print("Pencatatan selesai")
text Keluaran
Sensor 01: 28.5 derajat C
Pencatatan selesai

Tiga pemanggilan write menyusun satu baris utuh tanpa spasi tambahan, dan pemindah baris ditulis secara eksplisit dengan "\n". Baris terakhir memperlihatkan print yang melengkapi keluarannya dengan pemindah baris sendiri. Untuk format yang presisi, gabungkan io.write dengan string.format apabila lebar kolom atau jumlah angka desimal perlu diatur.

Waktu dengan os.time dan os.date#

Fungsi os.time(tabel) mengonversi komponen waktu yang diberikan sebagai table, seperti year, month, day, hour, dan min, menjadi epoch, yakni jumlah detik sejak 1 Januari 1970 pukul 00:00 UTC. Fungsi os.date(format, epoch) bergerak sebaliknya, yaitu menyusun string tanggal dari epoch sesuai kode format seperti %Y, %m, %d, %H, dan %M. Awalan ! pada format membaca epoch sebagai waktu UTC, sehingga keluarannya tidak terpengaruh zona waktu mesin.

lua Contoh: os.time dari komponen waktu
local t = os.time({ year = 2026, month = 11, day = 6, hour = 8, min = 30 })
print(t)
print(os.date("!%Y-%m-%d %H:%M", t))
text Keluaran
1793953800
2026-11-06 08:30

Pemanggilan os.time mengembalikan 1793953800 di mesin UTC, dan os.date dengan tanda ! mengubahnya kembali menjadi 2026-11-06 08:30. Pasangan dua arah seperti ini menjadi dasar menyimpan cap waktu (timestamp) ke dalam data dan menampilkannya kembali sesuai kebutuhan.

lua Contoh: os.date dengan epoch tetap dan bentuk UTC
local epoch = 1793953800
print(os.date("!%d/%m/%Y", epoch))
print(os.date("!%H:%M:%S", epoch))
print(os.date("!%Y-%m-%d %H:%M", epoch))
print(os.date("!%A, %d %B %Y", epoch))
text Keluaran
06/11/2026
08:30:00
2026-11-06 08:30
Friday, 06 November 2026

Kode %d/%m/%Y menyusun tanggal gaya umum, %H:%M:%S menyusun jam, sedangkan %A dengan %B menampilkan nama hari serta nama bulan. Nama tersebut mengikuti pengaturan locale penerjemah, yang pada sistem bawaan berbahasa Inggris, sehingga muncul “Friday, 06 November 2026”. Untuk cap waktu log yang konsisten antarmesin, bentuk !%Y-%m-%d %H:%M:%S adalah pilihan yang paling aman.

Mengelola berkas dengan os.rename dan os.remove#

Fungsi os.rename(lama, baru) mengganti nama atau memindahkan berkas, sedangkan os.remove(nama) menghapusnya. Keduanya mengembalikan true apabila berhasil dan nil beserta pesan error apabila gagal, misalnya karena berkasnya tidak ada. Skrip berikut membuat berkas latihan, mengganti namanya, membaca isinya, lalu menghapusnya.

lua kelola-berkas.lua
-- Mengelola berkas latihan dengan os.rename dan os.remove
local f = io.open("latihan.txt", "w")
f:write("isi awal")
f:close()

os.rename("latihan.txt", "catatan-lama.txt")

local ada = io.open("latihan.txt", "r") ~= nil
print("latihan.txt ada      : " .. tostring(ada))

local g = io.open("catatan-lama.txt", "r")
print("isi catatan-lama.txt : " .. g:read("a"))
g:close()

os.remove("catatan-lama.txt")
ada = io.open("catatan-lama.txt", "r") ~= nil
print("catatan-lama.txt ada : " .. tostring(ada))
text Keluaran
latihan.txt ada      : false
isi catatan-lama.txt : isi awal
catatan-lama.txt ada : false

Setelah rename, berkas lama tidak ditemukan lagi, sehingga io.open("latihan.txt", "r") mengembalikan nil dan pembandingannya mencetak false. Isi berkas baru tetap utuh karena rename hanya mengubah nama, bukan isinya. Penghapusan di akhir memastikan direktori kembali bersih, dan pemeriksaan kedua mengonfirmasi bahwa berkasnya sudah tidak ada.

Batasan pustaka pada lingkungan tersemat#

Lua dirancang untuk disematkan, sehingga aplikasi host menentukan pustaka mana yang disertakan ke dalam lingkungannya. Host seperti Redis menyediakan Lua untuk skrip tetapi meniadakan io dan sebagian besar os, karena skrip Redis harus aman dan deterministik saat direplikasi. Gim dan aplikasi tersemat lain juga sering menyertakan hanya sebagian pustaka standar, sehingga io.open, os.remove, atau os.getenv bisa saja tidak ada sama sekali.

Keterbatasan yang sama menimpa os.getenv, yang dapat mengembalikan nil untuk variabel apa pun karena host sering mengosongkan lingkungan eksekusinya. Praktik yang aman adalah memperlakukan nilai lingkungan sebagai opsi yang menyediakan nilai bawaan di dalam kode. Dengan disiplin ini, skrip yang sama berjalan penuh di penerjemah mandiri dan tetap aman saat disematkan pada aplikasi host.

Ringkasan#

  • io.open mengembalikan objek berkas dengan mode w, a, atau r, dan kegagalan mengembalikan nil beserta pesan error, bukan melempar error.
  • read("l"), read("L"), dan read("a") membaca baris, baris dengan pemindah baris, dan seluruh sisa isi, sedangkan lines mengulang baris demi baris dan close menutup berkas.
  • io.write menulis apa adanya tanpa pemindah baris, berbeda dengan print yang menambah pemisah TAB dan baris baru.
  • os.time mengonversi komponen waktu menjadi epoch yang bergantung zona waktu, os.date dengan tanda ! menampilkannya sebagai UTC, os.rename dan os.remove mengelola berkas, sedangkan host tersemat sering menonaktifkan io dan os.

Referensi#