I/O Dasar

Membaca masukan dengan Scanner, menampilkan keluaran rapi dengan System.out.printf, dan membiasakan validasi.

Daftar isi

Topik ini menghubungkan program Java dengan dunia luarnya pada dua arah sekaligus, yaitu membaca masukan dan menampilkan keluaran. Kelas Scanner dipakai untuk memilah teks menjadi angka dan kata, System.out.printf merapikan tampilan angka, dan kebiasaan memeriksa masukan sebelum dibaca ditanam sejak awal. Seluruh contoh membaca dari String agar dapat dijalankan tanpa mengetik apa pun, sedangkan cara mengganti sumbernya dengan ketikan pengguna dijelaskan pada bagian pertama.

Membaca masukan dengan Scanner#

Kelas Scanner memilah teks menjadi potongan bernama token, yaitu deretan karakter yang dipisahkan spasi, tab, atau baris baru. Baris 80 75 92 diurai menjadi tiga token angka tanpa menulis pemecahan String manual, karena pekerjaan itu sudah diurus Scanner. Konstruktornya menerima sumber teks apa pun, mulai dari String, berkas, sampai aliran ketikan pengguna, dan cara pembacaannya sama untuk semua sumber.

Metode nextInt() membaca token berikutnya, mengubahnya menjadi int, lalu menggeser posisi pembacaan ke token setelahnya. Metode next() membaca token apa pun sebagai String, sedangkan nextLine() mengambil seluruh sisa baris. Program berikut menguraikan satu baris berisi tiga nilai ujian, lalu menghitung rata-ratanya.

java PembacaanScanner.java
import java.util.Scanner;

public class PembacaanScanner {
    public static void main(String[] args) {
        String barisNilai = "80 75 92";
        Scanner pemindai = new Scanner(barisNilai);

        int nilaiSatu = pemindai.nextInt();
        int nilaiDua = pemindai.nextInt();
        int nilaiTiga = pemindai.nextInt();

        double rataRata = (nilaiSatu + nilaiDua + nilaiTiga) / 3.0;

        System.out.println("Nilai     : " + nilaiSatu + ", " + nilaiDua + ", " + nilaiTiga);
        System.out.println("Rata-rata : " + rataRata);
        pemindai.close();
    }
}
text Keluaran
Nilai     : 80, 75, 92
Rata-rata : 82.33333333333333

Baris 80 75 92 dikonsumsi token demi token, sehingga tiga pemanggilan nextInt() menghasilkan 80, 75, dan 92. Posisi pembacaan Scanner bergerak maju saja, dan pemanggilan berikutnya selalu melanjutkan dari token yang belum terbaca. Pemanggilan close() menutup sumber masukan, dan kebiasaan ini pantas dipertahankan meskipun pada program kecil peninggalannya tidak terasa.

Pada program yang benar-benar dipakai, sumber Scanner biasanya System.in, yaitu ketikan pengguna di terminal. Bentuk lengkapnya seperti berikut. Program berhenti di nextInt() sampai angka diketik dan Enter ditekan, sehingga contoh semacam ini tidak dapat dijalankan di lingkungan tanpa masukan.

java Contoh: membaca ketikan pengguna lewat System.in
// tidak-dijalankan
import java.util.Scanner;

public class NilaiUjian {
    public static void main(String[] args) {
        Scanner masukan = new Scanner(System.in);

        System.out.print("Masukkan nilai: ");
        int nilai = masukan.nextInt();

        System.out.println("Nilai yang dimasukkan: " + nilai);
        masukan.close();
    }
}

Keluaran rapi dengan printf#

System.out.printf mencetak teks menurut pola yang ditentukan pada format string, yakni String pertama yang memuat spesifikasi format seperti %s, %d, dan %f. Setiap spesifikasi digantikan oleh argumen berurutan yang mengikutinya, sedangkan %n mencetak pemisah baris. Dengan pola ini, posisi teks, jumlah desimal, dan lebar kolom diatur pada satu tempat, alih-alih dirakit lewat rangkaian penggabungan String.

java LaporanPrintf.java
public class LaporanPrintf {
    public static void main(String[] args) {
        String nama = "Citra";
        int jumlahBarang = 3;
        double total = 45000.0;

        System.out.printf("Pembeli    : %s%n", nama);
        System.out.printf("Jumlah     : %d buah%n", jumlahBarang);
        System.out.printf("Total      : Rp%.2f%n", total);
        System.out.printf("Total rapi : Rp%12.2f%n", total);
        System.out.printf("Kode nota  : %05d%n", 42);
    }
}
text Keluaran
Pembeli    : Citra
Jumlah     : 3 buah
Total      : Rp45000.00
Total rapi : Rp    45000.00
Kode nota  : 00042

Spesifikasi %12.2f menampilkan angka pecahan dalam kolom selebar 12 karakter dengan dua angka di belakang titik desimal, sehingga angkanya rata di sisi kanan kolom. Spesifikasi %05d melengkapi bilangan bulat dengan nol di depan sampai panjangnya lima, cocok untuk kode nota seperti 00042. Pembulatan pada %.2f hanya terjadi di tampilan, sedangkan variabel total tetap menyimpan nilai penuh untuk perhitungan berikutnya. Bila hasilnya perlu disimpan sebagai teks dan bukan dicetak langsung, metode String.format menerima format yang sama dan mengembalikan String-nya.

SpesifikasiKegunaanContohTampilan
%steks%s dengan CitraCitra
%dbilangan bulat%d dengan 4242
%05dbilangan bulat dengan nol di depan%05d dengan 4200042
%.2fpecahan dengan dua desimal%.2f dengan 45000.045000.00
%12.2fpecahan dalam kolom selebar 12 karakter%12.2f dengan 45000.0empat spasi di depan, lalu 45000.00

Memeriksa masukan sebelum dibaca#

Keluarga hasNext memeriksa token berikutnya tanpa mengambilnya. Metode hasNextInt() bernilai true bila token berikutnya dapat dibaca sebagai int, hasNext() bernilai true bila masih ada token apa pun, dan hasNextLine() bernilai true bila masih ada baris tersisa. Pola periksa dahulu, baca kemudian, mencegah InputMismatchException sebelum sempat muncul.

Program berikut memeriksa tiga token yang berbeda sifatnya tanpa membaca angkanya lebih dahulu.

java ValidasiMasukan.java
import java.util.Scanner;

public class ValidasiMasukan {
    public static void main(String[] args) {
        String masukan = "12 abc 34";
        Scanner pemindai = new Scanner(masukan);

        System.out.println("Token 1 berupa angka: " + pemindai.hasNextInt());
        pemindai.next();
        System.out.println("Token 2 berupa angka: " + pemindai.hasNextInt());
        pemindai.next();
        System.out.println("Token 3 berupa angka: " + pemindai.hasNextInt());
        pemindai.close();
    }
}
text Keluaran
Token 1 berupa angka: true
Token 2 berupa angka: false
Token 3 berupa angka: true

Masukan berupa 12 abc 34 menghasilkan pola true, false, true. Token abc ditandai false, dan pemanggilan next() setelahnya berperan membuang token itu agar posisi pembacaan maju ke 34. Tanpa pembuangan itu, hasNextInt() berikutnya masih memeriksa token abc yang sama.

Pola ini diperluas menjadi perulangan yang menunggu sampai token yang sah ditemukan.

java Contoh: mengulang sampai token berupa angka
// tidak-dijalankan
while (!pemindai.hasNextInt()) {
    System.out.println("Dilewati, bukan angka: " + pemindai.next());
}
int angka = pemindai.nextInt();
System.out.println("Angka yang sah: " + angka);

Perulangan terus membuang token yang tidak sah lewat next() sampai angka ditemukan. Pada sumber String, pastikan ada angka yang sah di dalamnya, karena perulangan ini berhenti hanya ketika token habis. Pola yang sama bekerja pada System.in. Di sini perulangan menunggu ketikan yang memang berupa angka.

Kesalahan umum#

  • nextInt() dipanggil untuk token abc tanpa pemeriksaan, sehingga program berhenti dengan InputMismatchException. Perbaikannya memeriksa dahulu dengan hasNextInt(), sebagaimana pola periksa lalu baca.
  • nextLine() dipanggil setelah nextInt() dan mengembalikan teks kosong. Metode nextInt() tidak mengkonsumsi pemisah baris di belakang angka, sehingga nextLine() mengambil sisa baris yang berisi pemisah itu saja. Perbaikannya memanggil nextLine() satu kali tambahan sebelum membaca baris berikutnya.
  • %d diberi nilai pecahan, misalnya printf("%d", total) dengan total bertipe double, sehingga muncul IllegalFormatConversionException. Perbaikannya memakai %f untuk pecahan atau mengubah nilainya menjadi int bila memang diinginkan.
  • Mengira pembulatan %.2f mengubah nilai variabel. printf hanya membentuk tampilan, dan variabelnya tetap menyimpan nilai penuh untuk perhitungan berikutnya.
  • Mengira nextInt() membaca seluruh baris ketikan. Metode itu hanya membaca satu token, sehingga baris berisi tiga angka harus dibaca dengan tiga pemanggilan, atau dibaca utuh dengan nextLine() lebih dahulu lalu diurai sendiri.

Ringkasan#

  • Scanner memilah sumber teks menjadi token dan membacanya berurutan dengan nextInt(), next(), serta nextLine(), baik dari String maupun dari System.in.
  • System.out.printf mencetak menurut spesifikasi %s, %d, %f beserta lebar dan presisinya, dengan %n sebagai pemisah baris yang portabel.
  • hasNextInt() memeriksa token berikutnya tanpa membacanya, dan pola periksa dahulu mencegah InputMismatchException.
  • close() menutup sumber Scanner setelah pembacaan selesai.

Referensi#