Pola nextLine() diikuti Integer.parseInt pada Chapter sebelumnya sebenarnya adalah cara kerja alat input yang lebih tua dan lebih cepat: BufferedReader. Class dari package java.io ini telah lama menjadi pilihan utama untuk input berbasis teks sejak versi awal Java, dan hingga kini masih dipakai luas untuk membaca baris demi baris — dari keyboard, berkas, hingga koneksi jaringan. Chapter ini membahas cara menyusun lapisan BufferedReader, arti IOException yang wajib ditangani, serta cara memilih antara BufferedReader dan Scanner.
Membungkus System.in dengan BufferedReader #
BufferedReader tidak bisa membaca System.in secara langsung karena System.in menghasilkan byte, sedangkan BufferedReader bekerja dengan karakter. Karena itu kita perlu dua lapisan: InputStreamReader menerjemahkan byte menjadi karakter (proses decoding), lalu BufferedReader menambahkan penyangga (buffer) di atasnya. Tanpa buffer, setiap pembacaan karakter dapat memicu panggilan sistem operasi yang mahal; dengan buffer, data dibaca dalam potongan besar sekali jalan lalu dibagikan sedikit demi sedikit oleh method readLine().
Mari kita lihat bentuk lengkapnya pada program sapaan sederhana:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BacaNamaBuffer {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Nama: ");
String nama = br.readLine();
System.out.print("Umur: ");
String umurTeks = br.readLine();
int umur = Integer.parseInt(umurTeks);
System.out.println("Halo, " + nama + "! Tahun depan Anda berumur " + (umur + 1) + " tahun.");
}
}Output yang Dihasilkan:
Nama: Umur: Halo, Budi! Tahun depan Anda berumur 18 tahun.Mari kita telaah baris-baris kode di atas:
- Baris 1-3 (
import java.io.*): ketiga class pendukung diimpor dari packagejava.io—BufferedReader,IOException, danInputStreamReader. - Baris 6 (
throws IOException):readLine()dideklarasikan dapat melempar checked exception, sehingga compiler memaksa kita menyatakan niat: diteruskan denganthrowsseperti di sini, atau ditangani dengantry-catchseperti contoh kedua di bawah. - Baris 7 (
new BufferedReader(new InputStreamReader(System.in))): dua lapisan disusun dari dalam ke luar —InputStreamReadermembungkusSystem.in,BufferedReadermembungkusInputStreamReader. - Baris 10 dan 13 (
br.readLine()): setiap panggilan mengembalikan satu baris ketikan sebagaiStringtanpa tanda baris barunya. - Baris 14 (
Integer.parseInt(umurTeks)): konversi teks menjadiintdilakukan manual — di sinilah letak perbedaan utama denganScanner.nextInt()yang mengonversi otomatis.
IOException sebagai Checked Exception #
Mengapa readLine() sampai wajib menangani exception? Jawabannya ada pada kenyataan bahwa pembacaan input adalah operasi terhadap perangkat: keyboard bisa terputus, berkas bisa hilang saat dibaca, koneksi bisa terputus di tengah jalan. Perancang java.io memutuskan kegagalan semacam ini terlalu serius untuk disembunyikan, sehingga IOException dibuat sebagai checked exception — compiler menolak kode yang membacanya tanpa throws atau try-catch.
Pada contoh pertama, klausa throws IOException di main berarti “biarkan JVM yang menangani”. Jika exception benar-benar terjadi, JVM mencetak stack trace lalu menghentikan program — perilaku yang dapat diterima untuk program kecil, tetapi kurang sopan bagi pengguna aplikasi sungguhan. Sebagai perbandingan, class Scanner menelan IOException di dalam implementasinya dan menampilkannya sebagai kegagalan pembacaan biasa; itulah salah satu alasan Scanner terasa lebih “bersih” bagi pemula.
Membaca Banyak Baris dengan Try-with-Resources #
Untuk input yang panjang, pola yang tepat adalah loop while dengan dua syarat berhenti: baris bernilai null atau baris berisi kata kunci penutup. Nilai null adalah cara readLine() menyatakan bahwa stream telah habis — tidak ada lagi data yang bisa dibaca. Program berikut menjumlahkan angka sampai pengguna mengetik kata selesai, melompati baris yang bukan angka, sekaligus memakai try-with-resources agar reader tertutup otomatis:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class BacaAngkaBuffer {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(System.in, StandardCharsets.UTF_8))) {
int total = 0;
int jumlah = 0;
String baris;
while ((baris = br.readLine()) != null && !baris.equalsIgnoreCase("selesai")) {
try {
total += Integer.parseInt(baris);
jumlah++;
} catch (NumberFormatException e) {
System.out.println("Dilewati (bukan angka): " + baris);
}
}
System.out.println("Jumlah angka: " + jumlah);
System.out.println("Total : " + total);
} catch (IOException e) {
System.out.println("Gagal membaca input: " + e.getMessage());
}
}
}Output yang Dihasilkan:
Dilewati (bukan angka): abc
Jumlah angka: 2
Total : 40Poin penting dari program ini dapat diuraikan begini:
- Baris 8-9 (
try (BufferedReader br = ...)): try-with-resources menjaminclose()dipanggil otomatis saat blok berakhir — kebocoran resource tidak mungkin terjadi walau exception meloncat di tengah proses. - Baris 9 (
StandardCharsets.UTF_8): charset dinyatakan secara eksplisit sehingga decoding byte ke karakter tidak bergantung pada pengaturan platform tempat program berjalan. - Baris 14 (
(baris = br.readLine()) != null): assignment di dalam kondisi membaca satu baris sekaligus menyimpannya; saat stream habis,readLine()mengembalikannulldan loop berhenti rapi tanpa exception. - Baris 15-20 (
Integer.parseIntdanNumberFormatException): baris non-angka tidak menghentikan program —NumberFormatExceptionditangkap, baris tersebut dilewati dengan pesan, lalu loop berlanjut ke baris berikutnya.
Scanner atau BufferedReader #
Kedua alat tersebut tumpang tindih fungsinya, tetapi masing-masing punya wilayah yang paling pas:
| Aspek | Scanner | BufferedReader |
|---|---|---|
| Satuan bacaan | token (kata) atau baris | baris saja |
| Konversi angka | otomatis (nextInt dan sejenisnya) | manual (Integer.parseInt) |
| Input salah tipe | InputMismatchException | NumberFormatException dari parseInt |
| Exception pembacaan | ditelan implementasi | IOException wajib dideklarasikan |
| Kekuatan khas | parsing token campuran, delimiter kustom | volume baris besar, minimal overhead |
Untuk form interaktif dengan campuran angka dan teks, Scanner lebih ringkas. Untuk pipeline data baris demi baris — menjumlahkan log, membaca CSV sederhana, memproses keluaran program lain — BufferedReader lebih ringan dan lebih mudah dikendalikan. Dengan input yang sudah terbaca, langkah berikutnya adalah menampilkan hasil yang rapi; Chapter Mencetak Output membahas sisi lawannya: print, println, dan escape sequence.
Referensi #
- Oracle: BufferedReader (Java SE 25 API)
- Oracle: InputStreamReader (Java SE 25 API)
- Oracle: Integer.parseInt (Java SE 25 API)
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
BacaAngkaBuffer.java
Unduh berkasimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
public class BacaAngkaBuffer {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(
new InputStreamReader(System.in, StandardCharsets.UTF_8))) {
int total = 0;
int jumlah = 0;
String baris;
while ((baris = br.readLine()) != null && !baris.equalsIgnoreCase("selesai")) {
try {
total += Integer.parseInt(baris);
jumlah++;
} catch (NumberFormatException e) {
System.out.println("Dilewati (bukan angka): " + baris);
}
}
System.out.println("Jumlah angka: " + jumlah);
System.out.println("Total : " + total);
} catch (IOException e) {
System.out.println("Gagal membaca input: " + e.getMessage());
}
}
}
BacaNamaBuffer.java
Unduh berkasimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class BacaNamaBuffer {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.print("Nama: ");
String nama = br.readLine();
System.out.print("Umur: ");
String umurTeks = br.readLine();
int umur = Integer.parseInt(umurTeks);
System.out.println("Halo, " + nama + "! Tahun depan Anda berumur " + (umur + 1) + " tahun.");
}
}