Input utente in Java con Scanner
Leggi input dalla console in Java con la classe Scanner — nextInt, nextDouble, nextLine e validazione dell'input.
Per la maggior parte dei programmi per principianti, il modo più semplice per leggere input dalla tastiera è java.util.Scanner. Esso racchiude System.in (il flusso di input standard) e fornisce metodi come nextInt, nextDouble e nextLine. Questo capitolo tratta le API di Scanner, il famoso problema del "Scanner che salta una riga" e le alternative da considerare quando Scanner non è più adeguato.
Configurare uno Scanner
Scanner si trova in java.util, quindi è necessario un import:
import java.util.Scanner;
public class Greeter {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("What is your name? ");
String name = in.nextLine();
System.out.println("Hello, " + name + "!");
}
}Scanner dovrebbe essere chiuso quando non è più necessario — ma se si chiude uno scanner su System.in, si chiude anche l'input standard per il resto del programma. Per script brevi va bene omettere close(). Per codice più lungo, usa try-with-resources per gli scanner su file, ma non per System.in.
I metodi di lettura
| Metodo | Legge |
|---|---|
nextLine() | il resto della riga corrente (esclude \n) |
next() | il prossimo token delimitato da spazi bianchi |
nextInt() | il prossimo token, interpretato come int |
nextLong() | …come long |
nextDouble() | …come double |
nextBoolean() | …come boolean |
hasNext() | true se è disponibile un altro token |
hasNextInt() | true se il prossimo token è un intero valido |
hasNextLine() | true se è disponibile un'altra riga |
Usa le varianti hasNext... per validare l'input prima di leggerlo.
Un ciclo di richiesta completo
import java.util.Scanner;
public class Calculator {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("First number: ");
double a = in.nextDouble();
System.out.print("Second number: ");
double b = in.nextDouble();
System.out.println("Sum: " + (a + b));
}
}Se l'utente digita un valore non numerico, nextDouble lancia un'eccezione InputMismatchException. Vedremo come gestirla di seguito.
Il problema classico — nextInt lascia un a-capo nel buffer
Dopo nextInt() o nextDouble(), lo scanner lascia il carattere di nuova riga nel buffer. La successiva chiamata a nextLine() restituirà quindi una stringa vuota:
System.out.print("age? ");
int age = in.nextInt(); // user types "30" then Enter
System.out.print("name? ");
String name = in.nextLine(); // returns "" — the leftover newline
String name2 = in.nextLine(); // returns the typed nameDue soluzioni comuni:
- Dopo
nextInt()/nextDouble(), chiamain.nextLine()per scartare il resto della riga. - Usa
nextLine()ovunque e analizza la stringa manualmente:
System.out.print("age? ");
int age = Integer.parseInt(in.nextLine().trim());Il secondo approccio è più pulito quando si inizia a gestire la validazione.
Validare con hasNext...
Scanner in = new Scanner(System.in);
System.out.print("Enter a number: ");
while (!in.hasNextInt()) {
System.out.print("That isn't an integer. Try again: ");
in.next(); // discard the bad token
}
int value = in.nextInt();
System.out.println("You entered: " + value);Leggere fino a EOF
Un pattern comune per l'elaborazione batch — leggi finché l'utente non digita Ctrl+D (Linux/macOS) o Ctrl+Z seguito da Invio (Windows):
Scanner in = new Scanner(System.in);
int total = 0;
while (in.hasNextInt()) {
total += in.nextInt();
}
System.out.println("Total: " + total);BufferedReader — quando Scanner non è abbastanza veloce
Per la programmazione competitiva o in qualsiasi contesto in cui si leggono decine di migliaia di righe, BufferedReader è significativamente più veloce di Scanner:
import java.io.BufferedReader;
import java.io.InputStreamReader;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int n = Integer.parseInt(line.trim());Richiede un po' più di codice, ma un'accelerazione di 10–20× è comune.
System.console() — solo sessioni interattive
Quando il programma è collegato a un terminale reale, System.console() restituisce un oggetto Console con readLine e readPassword (che non mostra i caratteri digitati):
java.io.Console c = System.console();
if (c != null) {
String user = c.readLine("Username: ");
char[] pass = c.readPassword("Password: ");
// ... use pass ...
java.util.Arrays.fill(pass, ' '); // zero out the password buffer
}System.console() restituisce null quando il programma viene eseguito tramite un IDE che reindirizza stdin, quindi non fare affidamento su di esso per l'input generale.
Una dimostrazione
Il codice eseguibile di seguito usa System.in. Il runner non fornisce input interattivo, quindi questa versione legge da una stringa fissa — simile a come viene normalmente utilizzato Scanner:
Cosa c'è dopo
La Parte 2 si conclude qui. La parte successiva, Flusso di controllo, inizia con Java if, else e else if e prosegue con switch e i cicli che guidano la maggior parte della logica dei programmi.