Java Scanner zum Einlesen von Benutzer-Eingaben

In Java mit der Klasse Scanner Strings usw. einlesen. Wie deine Eingaben gegen dumme oder bösartige User absicherst, und Probleme vermeidest.Tags: | |
Noch nicht sicher genug im Webdesign? Lass dir in unseren Programmier-Kursen in Kirchdorf oder unserer Wichtel-Webdesign-Agentur in Pettenbach weiterhelfen!

Worum geht´s?

In diesem Tutorial geht es um das Einlesen von Benutzer-Eingaben mit Hilfe der Scanner-Klasse in der Programmiersprache Java. Die Scanner-Klasse ist grundsätzlich recht einfach zu benützen, hat aber einige kleine Besonderheiten, die man wissen sollte.

1. Java Scanner: Was ist das, und wofür brauche ich ihn?

Die Scanner-Klasse in Java kannst du dir in etwa so vorstellen wie ein Druckgerät, mit dem du auch scannen kannst. Genau wie du mit einem einzigen Scan-Gerät mehrere Dokumente einscannen kannst, kannst du mit der Scanner-Klasse in Java auch mehrere Variablen einscannen.

Du brauchst also üblicherweise für Benutzer-Eingaben nicht mehrere Scanner-Variablen, sondern nur eine einzige – eben wie bei einem einzelnen Scan-Gerät, das mehrere Bilder etc. einscannen kann.

Da wir mit Hilfe der Scanner-Klasse nicht nur Benutzer-Eingaben, sondern zum Beispiel auch Dateien auslesen können, müssen wir dem Programm beim Erstellen der Scanner-Klasse auch mitteilen, woher er seinen „Input“ denn beziehen soll.

Um Benutzer-Eingaben aus der Konsole verarbeiten zu können, sagen wir unserem Scanner, dass er auf System.in „horchen“ soll. Das ist gewissermaßen der Gegenpol zu System.out, das wir ja schon aus der Konsolen-Ausgabe kennen.

Um also z.B. in Java eine int-Variable mit Benutzer-Eingaben einlesen zu können, könnten wir das so lösen:

Scanner sc = new Scanner(System.in);
int alter = sc.nextInt();

Was jetzt noch fehlt, ist das Importieren der Scanner-Klasse in unser Programm (deswegen wird „Scanner“ vermutlich bei dir noch als Fehler angezeigt).

1.1 Die Scanner-Klasse in Java importieren

In Java gibt es sehr viele vorgefertigte Funktionen, die meist in Form von Klassen gestaltet sind. Will man diese verwenden, so muss man die entsprechende Java-Klasse erst importieren.

Dies macht man mit Hilfe des Befehls „import“ und der entsprechenden Klasse. Damit Java die richtige Klasse findet, muss man nicht nur den Namen der Klasse angeben, sondern auch ihre „Ordnerstruktur“ – die heißt in Java „packages“.

Statt „import Scanner;“ schreiben wir also „import java.util.Scanner;“ – und zwar ganz oben in unserer Java-Klasse, also noch vor dem „public class nameMeinerKlasse() {„-Bereich:

import java.util.Scanner;
public class HelloWorld {

Falls du zum Programmieren mit Java das Programm IntelliJ benützt, kannst du auch einfach mit der Maus auf eine Klasse klicken die du importieren möchtest, und dann die Tastenkombination ALT + ENTER. Handelt es sich um eine der Standard-Klassen in Java, wird sie automatisch für dich importiert.

1.2 Die Aufforderung zur Benutzer-Eingabe hinzufügen

Wenn wir nur den Scanner anlegen und eine Variable einlesen, dann weiß der Benutzer ja nicht, was er jetzt machen soll.

Um das zu ändern, sollten wir dem Benutzer eine entsprechende Nachricht anzeigen.

Eine Aufforderung, das eigene Alter anzugeben, könnte z.B. in etwa so aussehen:

Scanner sc = new Scanner(System.in);
System.out.println("Gib bitte dein Alter an");
int alter = sc.nextInt();

Mit unserer alter-Variable können wir nun genau so umgehen als hätten wir den Wert der Variable selbst vordefiniert gehabt (z.B. mit int alter = 3;).

2. Nicht nur int-Variablen: boolean, double, char und Strings mit dem Java Scanner einlesen

Netterweise funktioniert die Eingabe von Variablen der Datentypen boolean und double so ziemlich genau gleich wie mit int-Variablen.

Einzig der Datentyp nach dem .nextInt() ändert sich eben dann z.B. zu .nextBoolean(), wenn ein boolean eingegeben werden soll. Und natürlich auch der Datentyp der Variable, in die das Ergebnis gespeichert werden soll:

double preis = sc.nextDouble();
boolean fuehrerschein = sc.nextBoolean();

Etwas komplizierter wird es bei Strings und char-Eingaben.

Wenn du einen String mit der Klasse Scanner einlesen willst, darfst du dafür nicht .nextString() schreiben, sondern musst stattdessen .nextLine() verwenden.

Beim Datentyp char schreibst du überhaupt gleich nur .next() – das heißt so viel wie „alles was eingegeben wird“. Damit davon nur 1 Zeichen gespeichert wird (eben ein char), fügst du noch ein .charAt(0) hinzu. Dies nimmt aus einer Zeichenkette den char an der Position 0 heraus (natürlich würde auch zum Beispiel .charAt(4) für das 5. Element funktionieren, falls du das mal brauchst):

String vorname = sc.nextLine();
char geschlecht = sc.next().charAt(0);

3. Den Benutzer so lange eingeben lassen, bis er es richtig macht

Oft ist es notwendig, die Eingabe des Benutzers zu überprüfen, damit keine sinnlosen oder sogar schädlichen Konsequenzen entstehen können.

Eine Möglichkeit, dies zu tun, ist ein klassisches IF – passt die Eingabe nicht, so bricht z.B. das Programm ab bzw. übersprint gewisse Teile.

Eine meist sinnvollere Möglichkeit ist es, den Benutzer in einer Schleife zu halten, bis er eine sinnvolle Eingabe getätigt hat.

Die Schleife, die sich dafür am besten eignet, ist die do-while-Schleife. Der User soll ja mindestens ein Mal einen Wert angeben. Passt dieser sofort, geht das Programm weiter. Passt er noch nicht, muss er noch einmal einen Wert eingeben.

Stellen wir uns vor, der Benutzer soll z.B. einen Kinofilm von 1-3 auswählen. Das könnten wir so lösen:

Scanner sc = new Scanner(System.in);
int auswahl;
do {
    System.out.println("Wähle einen Kinofilm (1-3)");
    auswahl = sc.nextInt();
} while (auswahl < 1 || auswahl > 3);
System.out.println("Du hast den Film " + auswahl + " gewählt");

Dieser Zugang hat den Vorteil im Vergleich zum einfachen IF, dass wir sichergehen können, dass der User nach der Schleife einen Wert angegeben hat, mit dem wir weiterarbeiten können.

Falls du dich fragst: Die Variable „auswahl“ musste deswegen außerhalb der do-while-Schleife deklariert werden, weil sie sonst bei der Überprüfung der Abbruch-Bedingung nicht existiert hätte.

4. Falsche Datentypen bei Eingaben in Java mit try und catch abfangen

Die obige Lösung unterbindet zwar, dass der Benutzer eine Zahl eingibt, die größer als 3 oder kleiner als 1 ist. Aber womit sie nicht umgehen kann sind Eingaben wie z.B. „drei“ (-> dummer Benutzer) oder auch „Doofnuss!“ (-> bösartiger Benutzer).

In beiden Fällen handelt es sich nicht um eine Zahl. Da das Programm aber eine Zahl als Eingabe erwartet, wird das Programm eine sogenannte Exception generieren – in diesem Fall eine „InputMismatchException“.

Wenn du jetzt nichts unternimmst, stürzt das Programm in einem solchen Fall einfach ab.

Willst du auch in diesem Fall reagieren können, brauchst du ein sogenanntes „Exception Handling“, das heißt du kümmerst dich um eventuelle Exceptions.

Was du dabei brauchst, ist ein sogenannter try-catch-Block rund um die „gefährliche“ Stelle im Code. Der sieht grob dann so aus:

System.out.println("Wähle einen Kinofilm (1-3)");
try {
    auswahl = sc.nextInt();
}
catch(Exception e) {
    // mach etwas, wenn ein Problem auftritt
}

Das Prinzip dahinter kannst du dir ähnlich wie bei einem IF vorstellen: Falls irgendwas ungewöhnliches passiert (eine Exception auftritt, man sagt auch „geworfen wird“), dann wird nachgeschaut, ob nach dem try-Block irgendein catch-Block kommt, der genau diese entsprechende Exception „auffängt“.

Du kannst nämlich in dem catch-Block nicht nur Exception schreiben, sondern eben auch z.B. InputMismatchException. Dann reagiert dieser catch-Block nur auf genau die Exception.

So kannst du auf verschiedene Probleme, die auftauchen könnten, verschieden reagieren.

In unserem Fall ist es uns relativ egal, was das Problem ist – sobald der User mit seiner Eingabe einen Fehler produziert, soll er nochmal eingeben müssen.

Dies können wir lösen, in dem z.b. eine boolean-Variable immer vor der Eingabe auf true setzen, und gibt es eine Exception, wird sie auf false gesetzt. In unserer do-while-Anweisung fügen wir dann noch als Voraussetzung dazu, dass die boolean-Variable auf true geblieben ist:

Scanner sc = new Scanner(System.in);
int auswahl = -1;
boolean noException;
do {
    noException = true;
    System.out.println("Wähle einen Kinofilm (1-3)");
    try {
        auswahl = sc.nextInt();
    }
    catch(Exception e) {
        // mach etwas, wenn ein Problem auftritt
        noException = false;
        sc.nextLine();
    }
} while (auswahl < 1 || auswahl > 3 || !noException);
System.out.println("Du hast den Film " + auswahl + " gewählt");

Dieser Code sollte auch dann noch funktionieren, wenn der User irgendeinen Text oder sonst etwas Seltsames eingibt.

5. Wenn die Aufforderung zur Benutzer-Eingabe vom Programm einfach übersprungen wird

Die Klasse Scanner hat eine etwas seltsame Eigenschaft, die bei Anfängern oft zur Verwirrung führt: Manchmal „überspringt“ der Scanner einfach Aufforderungen zur Benutzer-Eingabe.

5.1 Warum der Scanner in Java oft ignoriert wird

Im Hintergrund funktioniert System.in wie eine Art unendlich lange Zeichenkette. Immer wenn der User etwas eingibt, wird etwas hinten an die Zeichenkette drangefügt.

Unsere .nextInt(), .nextDouble() oder auch .nextLine() Befehle lesen diese unendlich lange Zeichenkette nach bestimmten Mustern aus.

Der Befehl .nextInt() z.B. sucht nach Zahlen, bis eine unterbrechendes Zeichen (z.B. eine ENTER-Taste) gefunden wurde.

Ist ein solches Zeichen gefunden worden, so wird alles davor „rausgenommen“ (also vorne von der unendlich langen Zeichenkette (= „stream“) entfernt, und kann stattdessen z.B. in einer Variable gespeichert werden.

Der Rest unserer unendlich langen Zeichenkette (einschließlich des ENTER-Zeichens) bleibt aber.

Kommt nun erneut ein .nextInt()-Befehl, obwohl das erste Zeichen unserer unendlich langen Zeichenkette immer noch ENTER ist, so glaub der Scanner, dass der Benutzer schon wieder was eingegeben hat.

5.2 Die Lösung des Problems

Um das zu verhindern, können wir eine Code-Zeile einfügen, die den Scanner dazu bringt, neu zu beginnen:

sc.nextLine();

Hier nochmal der Code-Block von oben, der funktionieren sollte, egal, was man eingibt. Das Grundprinzip dahinter ist übrigens recht universell einsetzbar:

Scanner sc = new Scanner(System.in);
int auswahl = -1;
boolean noException;
do {
    noException = true;
    System.out.println("Wähle einen Kinofilm (1-3)");
    try {
        auswahl = sc.nextInt();
    }
    catch(Exception e) {
        // mach etwas, wenn ein Problem auftritt
        noException = false;
        sc.nextLine(); // zurücksetzen des Scanners, damit man neu eingeben kann
    }
} while (auswahl < 1 || auswahl > 3 || !noException);
System.out.println("Du hast den Film " + auswahl + " gewählt");

Wir hoffen, damit hast du einen guten ersten Einblick in Benutzer-Eingaben in Java mit Hilfe der Scanner-Klasse bekommen 🙂

Diskussion zum Tutorial

Du bist aus Oberösterreich? Dann nütze doch auch unsere flexiblen Programmier-Kurse in Kirchdorf - oder gib deine Website gerne in die guten Hände unserer erfahrenen Wichtel-Webdesign-Agentur.