Interaksi dengan pengguna tidak hanya soal mencetak output — program juga perlu menerima input. Kotlin menyediakan beberapa function untuk membaca standard input (stdin), dan pilihannya berkembang dari masa ke masa. Function readLine() yang lama telah dideprecate sejak Kotlin 1.6 karena memaksa kita menangani String? padahal mayoritas kasus mengharapkan string non-null. Penggantinya adalah readln() dan readlnOrNull(), yang memisahkan jalan happy path (lempar exception saat EOF) dan defensive path (kembalikan null saat EOF). Pada chapter ini kita akan membandingkan ketiganya dan melihat pola membaca banyak baris input.
readLine() dan Mengapa Dideprecate #
Function readLine() mengembalikan String? — null jika stream stdin sudah mencapai EOF (End Of File). Desain ini membuat kode pemula dipenuhi ? dan !! meskipun ketika berjalan di terminal interaktif, EOF jarang terjadi. Sejak Kotlin 1.6, function ini ditandai sebagai deprecated, dan kompilator akan memberi peringatan jika kita tetap memakainya:
val nama = readLine() // String?, peringatan deprecation
val umur = readLine()!!.toInt() // !! berbahaya pada EOFUntuk menggantinya, Kotlin memperkenalkan dua function baru yang lebih jelas perannya. Pilih salah satu sesuai kebutuhan: kita ingin exception saat EOF, atau kita ingin menangani null secara eksplisit.
readln() dan readlnOrNull() #
| Function | Tipe kembalian | Perilaku saat EOF |
|---|---|---|
readln() | String | Melempar RuntimeException |
readlnOrNull() | String? | Mengembalikan null |
readLine() (deprecated) | String? | Mengembalikan null |
readln() adalah pilihan idiomatis ketika program kita berjalan di terminal interaktif dan EOF dianggap kondisi tak terduga. Sebaliknya, readlnOrNull() cocok untuk program yang menerima input dari file atau pipe, di mana EOF adalah akhir data yang wajar.
Contoh Membaca Input #
25
Bandung
Surabaya
42"}
fun main() {
println("Siapa nama Anda?")
val nama = readln()
println("Halo, $nama!")
println("Berapa umur Anda?")
val umur = readlnOrNull()
if (umur != null) {
println("Tahun depan Anda akan berumur ${umur.toInt() + 1}")
} else {
println("Input tidak terbaca")
}
println("Sebutkan dua kota favorit (satu per baris):")
val kota1 = readlnOrNull() ?: "Tanpa nama"
val kota2 = readlnOrNull() ?: "Tanpa nama"
println("Kota favorit: $kota1 dan $kota2")
println("Masukkan angka untuk diparsing (atau tekan Ctrl+D untuk EOF):")
val baris = readlnOrNull()
val angka = baris?.toIntOrNull() ?: 0
println("Angka yang dibaca: $angka")
}Output yang Dihasilkan:
Siapa nama Anda?
Halo, Budi!
Berapa umur Anda?
Tahun depan Anda akan berumur 26
Sebutkan dua kota favorit (satu per baris):
Kota favorit: Bandung dan Surabaya
Masukkan angka untuk diparsing (atau tekan Ctrl+D untuk EOF):
Angka yang dibaca: 42Mari kita telaah baris-baris kode di atas:
- Baris 2 (
println("Siapa nama Anda?")): program mencetak prompt terlebih dahulu agar pengguna tahu input apa yang diharapkan. Pola prompt-then-read ini umum di program CLI interaktif. - Baris 3 (
val nama = readln()): functionreadln()membaca satu baris dari stdin, menghapus karakter newline di akhir, dan mengembalikanStringnon-null. Jika stdin sudah EOF (misalnya pengguna menekan Ctrl+D),readln()akan melempar exception. - Baris 6 (
val umur = readlnOrNull()): functionreadlnOrNull()mengembalikanString?. Pemanggilan ini lebih defensif — jika EOF terjadi, kita mendapatnull, bukan exception. - Baris 7 (
if (umur != null)): setelah pengecekannull, smart cast Kotlin mengubah tipeumurmenjadiStringdi dalam blokif, sehingga kita dapat memanggilumur.toInt()tanpa operator!!. - Baris 13–14 (
readlnOrNull() ?: "Tanpa nama"): operator elvis?:memberikan nilai default"Tanpa nama"jikareadlnOrNull()mengembalikannull. Pola ini sangat berguna saat membaca banyak baris yang mungkin saja terputus di tengah. - Baris 18 (
baris?.toIntOrNull() ?: 0): kombinasi safe call?.dan elvis?:untuk parsing aman.toIntOrNull()mengembalikanInt?(null jika teks bukan angka valid), lalu elvis memberi nilai default0.
Membaca Banyak Baris #
Ketika program perlu membaca sejumlah baris, kita dapat menggunakan loop while yang berhenti ketika readlnOrNull() mengembalikan null:
fun main() {
var jumlah = 0
var baris: String?
while (true) {
baris = readlnOrNull() ?: break
jumlah++
println("Baris ke-$jumlah: $baris")
}
println("Total baris dibaca: $jumlah")
}Pola di atas adalah pola umum untuk Unix filter — program yang membaca stdin baris demi baris hingga EOF, melakukan pemrosesan, lalu menulis hasil ke stdout. Tool seperti cat, grep, dan wc bekerja dengan cara serupa.
Membaca Input dengan java.util.Scanner #
Untuk parsing yang lebih kompleks (membaca token per token, bukan baris per baris), Kotlin dapat memanfaatkan java.util.Scanner dari Java:
import java.util.Scanner
fun main() {
val scanner = Scanner(System.`in`)
print("Masukkan dua angka dipisah spasi: ")
val a = scanner.nextInt()
val b = scanner.nextInt()
println("Hasil: ${a + b}")
}Scanner memudahkan parsing tipe primitif langsung dari stdin tanpa perlu toInt() manual. Namun untuk membaca baris utuh, readln() tetap lebih ringkas dan idiomatis di Kotlin.
Referensi Lanjutan #
- Kotlin stdlib kotlin.io.readln
— halaman
kotlin.io.readlnuntuk membaca satu baris dari stdin - Kotlin stdlib kotlin.readln
— top-level function
readln()dikotlinpackage
Dengan kemampuan membaca input baris-per-baris, kita siap membahas function readln() lebih dalam pada chapter berikutnya — termasuk cara mengaitkannya dengan parsing bertingkat seperti readln().toInt().toString() dan penanganan galatnya.