W3docs

Java-Benutzereingabe mit Scanner

Konsoleneingaben in Java mit der Scanner-Klasse lesen – nextInt, nextDouble, nextLine und Eingabevalidierung.

Für die meisten Einsteigerprogramme ist java.util.Scanner der einfachste Weg, Eingaben von der Tastatur zu lesen. Es kapselt System.in (den Standard-Eingabestrom) und stellt Methoden wie nextInt, nextDouble und nextLine bereit. Dieses Kapitel behandelt die Scanner-API, den bekannten „Scanner überspringt eine Zeile"-Fallstrick und was verwendet werden kann, wenn Scanner nicht mehr ausreicht.

Scanner einrichten

Scanner befindet sich in java.util, daher wird ein import benötigt:

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 sollte geschlossen werden, wenn man fertig ist – aber wenn man einen Scanner über System.in schließt, wird auch die Standard-Eingabe für den Rest des Programms geschlossen. Bei kurzen Skripten ist es in Ordnung, close() wegzulassen. Bei längerem Code sollte try-with-resources für Scanner über Dateien verwendet werden, aber nicht für System.in.

Die Lesemethoden

MethodeLiest
nextLine()den Rest der aktuellen Zeile (ohne \n)
next()das nächste leerzeichen-getrennte Token
nextInt()das nächste Token, geparst als int
nextLong()…als long
nextDouble()…als double
nextBoolean()…als boolean
hasNext()true, wenn ein weiteres Token verfügbar ist
hasNextInt()true, wenn das nächste Token ein gültiger int ist
hasNextLine()true, wenn eine weitere Zeile verfügbar ist

Die hasNext...-Varianten können zur Validierung der Eingabe verwendet werden, bevor sie verarbeitet wird.

Eine vollständige Eingabeschleife

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));
    }
}

Wenn der Benutzer eine Nicht-Zahl eingibt, wirft nextDouble eine InputMismatchException. Den Umgang damit behandeln wir weiter unten.

Der klassische Fallstrick — nextInt lässt einen Zeilenumbruch zurück

Nach nextInt() oder nextDouble() verbleibt der abschließende Zeilenumbruch im Puffer. Das nächste nextLine() gibt dann einen leeren String zurück:

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 name

Zwei gängige Lösungen:

  • Nach nextInt() / nextDouble() einmal in.nextLine() aufrufen, um den Rest der Zeile zu verwerfen.
  • nextLine() überall verwenden und den String selbst parsen:
System.out.print("age? ");
int age = Integer.parseInt(in.nextLine().trim());

Der zweite Stil ist sauberer, sobald man mit der Validierung beginnt.

Validierung mit 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);

Bis EOF lesen

Ein häufiges Stapelverarbeitungsmuster – lesen, bis der Benutzer Ctrl+D (Linux/macOS) oder Ctrl+Z und dann Enter (Windows) drückt:

Scanner in = new Scanner(System.in);
int total = 0;
while (in.hasNextInt()) {
    total += in.nextInt();
}
System.out.println("Total: " + total);

BufferedReader — wenn Scanner nicht schnell genug ist

Für Wettbewerbsprogrammierung oder überall dort, wo Zehntausende von Zeilen gelesen werden, ist BufferedReader deutlich schneller als 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());

Es ist etwas mehr Code, aber eine 10–20-fache Beschleunigung ist üblich.

System.console() — nur für interaktive Sitzungen

Wenn das Programm an einem echten Terminal läuft, gibt System.console() ein Console-Objekt mit readLine und readPassword zurück (das keine Zeichen ausgibt):

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() gibt null zurück, wenn das Programm über eine IDE ausgeführt wird, die stdin umleitet. Daher sollte man sich nicht auf diese Methode für allgemeine Eingaben verlassen.

Eine Demonstration

Der ausführbare Code unten verwendet System.in. Der Runner stellt keine interaktive Eingabe bereit, daher liest diese Version stattdessen aus einem festen String – ähnlich wie Scanner normalerweise verwendet wird:

java— editable, runs on the server

Was kommt als Nächstes

Teil 2 endet hier. Der nächste Teil, Kontrollfluss, beginnt mit Java if, else und else if und geht weiter mit switch und den Schleifen, die den Großteil der Programmlogik antreiben.

Übungen

Übung
Warum gibt ein nachfolgendes scanner.nextLine() nach dem Aufruf von scanner.nextInt() oft einen leeren String zurück?
Warum gibt ein nachfolgendes scanner.nextLine() nach dem Aufruf von scanner.nextInt() oft einen leeren String zurück?
Was this page helpful?