Topic 1.13
Reading Keyboard Input with Scanner
In one line
java.util.Scanner reads text from the keyboard (or from a String or file) and splits it into tokens separated by whitespace, converting each one with nextInt, nextDouble, next or nextLine. Check with hasNextInt before you read, and watch out for the leftover line break after nextInt.
Think of it like this
A ticket clerk reading a queue of words. The clerk takes the next word in the queue each time you ask: 'give me a number' takes the next word and checks that it's a number; 'give me the rest of the line' takes everything up to the end of the current line. If you ask for a number and the next word is hello, the clerk refuses and raises an alarm. Scanner is that clerk; the queue is the text the user typed.
Words you'll meet
New words in this topic, in plain English. Come back here whenever one feels fuzzy.
- Input
- Data that comes into a program from outside: typed on a keyboard, read from a file, or received over a network.
- Standard input
- The program's default input stream,
System.in. In a terminal it is the keyboard; it can also be fed from a file. - Scanner
- A class in
java.utilthat reads text and hands it to you piece by piece, converting pieces to numbers when asked. - Token
- One piece of input between delimiters, such as
Ashaor42inAsha 42. - Delimiter
- The separator between tokens. For Scanner it is any whitespace by default: spaces, tabs and line breaks.
- Whitespace
- Characters you can't see but that make space: the space bar, tab and the line break from Enter.
- Blocking
- Waiting. A blocking call pauses the program until the data it needs arrives.
- Import
- A line at the top of a file, like
import java.util.Scanner;, that lets you use a class from another package by its short name. - Exception
- An error object Java throws while the program runs. If nothing catches it, the program stops and prints it (Phase 7).
Step by step
01Your first interactive program
Three lines do the work: the import, creating the Scanner, and asking it for values. print (not println) shows the question so the cursor waits on the same line.
This program needs a real keyboard, so run it in a terminal on your own machine. The examples further down use a fixed String instead, so they can run right here.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("Your name: ");
String name = in.nextLine();
System.out.print("Your age: ");
int age = in.nextInt();
System.out.print("Your height in metres: ");
double height = in.nextDouble();
System.out.println();
System.out.println("Hello, " + name + "!");
System.out.println("In 10 years you will be " + (age + 10) + ".");
System.out.printf("Your height is %.2f m.%n", height);
}
}02What happens when you type
While you type, the characters sit in the terminal, not in your program. Only when you press Enter does the terminal send the whole line, including the line break, to the program's standard input.
Inside, Scanner keeps a buffer (a holding area) of characters it has received but not yet handed out. Each next... call takes from the buffer; if the buffer doesn't hold a complete token yet, the call blocks and waits for more input.
03Tokens: whitespace separates, and line breaks are whitespace
Because line breaks count as whitespace, nextInt() doesn't care whether the user types 5 8 on one line or 5, Enter, 8 on two lines. Both give two tokens.
next() returns one token, so it can't read a full name with a space: for Asha Kumar it returns just Asha. Use nextLine() when spaces are part of the value.
04The nextInt then nextLine trap
Suppose the input is 25 Enter Asha Kumar Enter. nextInt() reads 25 and stops right before the line break. nextLine() then reads 'the rest of the current line', which is nothing, and returns "".
Fix 1: after nextInt(), call in.nextLine(); once and ignore the result. Fix 2 (more robust): read every value with nextLine() and convert it yourself with Integer.parseInt(line.strip()). Then each read takes exactly one line, and there's never a leftover.
05Check before you read
Users type mistakes. hasNextInt() answers 'is the next token a valid int?' without consuming it. If not, read it with next() to discard it, tell the user, and try again.
Note that after InputMismatchException the bad token is still in the buffer. A loop that just retries nextInt() will fail on the same token forever. Always consume it with next() or nextLine().
System.out.print("Enter a whole number: ");
while (!in.hasNextInt()) {
String bad = in.next(); // throw the bad token away
System.out.print(bad + " is not a whole number, try again: ");
}
int n = in.nextInt();06Locale and number formats
nextDouble() follows the Scanner's locale, which starts as the machine's default. A German locale reads 1,45 as one point four five and doesn't accept 1.45 as a double at all. Grouping separators are accepted too: with Locale.US, nextInt() reads 1,000 as 1000.
When your input has a fixed format (a file, test data, a contest), set it once: in.useLocale(Locale.US);.
07One Scanner, and don't close the keyboard
Creating a second new Scanner(System.in) in another method is a common source of 'lost' input: the first Scanner may already have pulled characters into its buffer, and the second one never sees them. Create one Scanner and pass it where it's needed.
in.close() closes the underlying stream too. For System.in that means the keyboard is gone for the rest of the program, and a later read throws NoSuchElementException. Close Scanners over files (with try-with-resources, Topic 7.6); for a Scanner over System.in it's fine to leave it open, and the operating system cleans up when the program ends.
Try it yourself
- 1
Run the keyboard program on your machine
Copy the first walkthrough program into
Main.javaon your computer, compile it withjavac Main.javaand runjava Mainin a terminal. Type your own name, age and height. Then run it again and typetwelvefor the age, and read the exception.terminal$ java Main── expected output ──Your name: Asha KumarYour age: twelveException in thread "main" java.util.InputMismatchExceptionat java.base/java.util.Scanner.throwFor(Scanner.java:947)at java.base/java.util.Scanner.next(Scanner.java:1602)at java.base/java.util.Scanner.nextInt(Scanner.java:2267)at java.base/java.util.Scanner.nextInt(Scanner.java:2221)at Main.main(Main.java:9) - 2
Change the fake keyboard
In 'Read numbers until the input ends', change the String to
"10 20 oops 30". Predict the count and sum before running. The loop stops atoopsbecausehasNextInt()is false there, so you get count 2 and sum 30;30is never read. - 3
Reproduce the trap
In the trap example, delete the second
name = in.nextLine();and its print. Now the program reports an empty name, exactly what happens to a real user who typed their age and then never got asked for their name.
Code & diagrams
With `new Scanner(System.in)` instead of the String, the same code reads from the keyboard. `nextDouble` uses your locale's decimal separator; on an English-language setup that's a dot.
Expected output
name: Asha
age: 12 (next year 13)
height: 1.45
member: true
more? false`while` loops are covered in Topic 2.5; here it just repeats as long as another whole number is waiting.
Expected output
count: 4
sum: 100
average: 25.0Expected output
age=25 name=[]
name=[Asha Kumar]
age2=25 name2=[Asha Kumar]Expected output
number: 12
skipped: abc
number: 7
skipped: x9
number: 30
US double: 1.45
US int: 1000
DE double: 1.45Expected output
1: 2 x milk
2: 1 x bread
3: 12 x eggsBreak it on purpose
Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.
Break #1
Type a word where a number is expected
Run the age program and type twelve.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print("How old are you? ");
int age = in.nextInt();
System.out.println("Next year you will be " + (age + 1));
}
}Break #2
Forget the import
Delete import java.util.Scanner;.
Break #3
Read more than there is
Scan the String "5 8" and call nextInt() three times.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner("5 8");
int a = in.nextInt();
int b = in.nextInt();
int c = in.nextInt();
System.out.println(a + b + c);
}
}Myth vs fact
Myth
nextInt() reads the whole line the user typed.
Fact
It reads one token and stops right before the line break. That leftover break is what makes a following nextLine() return empty text.
Myth
next() reads the user's full name.
Fact
next() reads one token, so Asha Kumar gives Asha. Use nextLine() when the value can contain spaces.
Myth
Every Scanner should be closed.
Fact
Close Scanners over files. Closing a Scanner over System.in closes the keyboard stream for the whole program; usually you leave it open.
Myth
Scanner is fine for any amount of input.
Fact
It's convenient but slow: it matches regular expressions for every token. For hundreds of thousands of numbers, BufferedReader with manual parsing is many times faster.
Pro corner
Extra depth for experienced readers. New to this? Skip it for now and come back later.
- ▸
Scanner is built on regular expressions (
java.util.regex, Topic 6.7):hasNextInt()matches the buffer against a locale-specific integer pattern that allows a sign and grouping separators.useDelimiter(",")swaps the whitespace delimiter for any pattern, which makes simple CSV-like input easy. - ▸
Scanner reads its source in chunks of 1024 characters into an internal buffer. That is why two Scanners on
System.inmisbehave: the first may have read characters the second will never see. - ▸
Scanner hides I/O errors: methods don't throw
IOException; insteadin.ioException()returns the last one.BufferedReader.readLine()reports them directly, another reason servers and file-processing code prefer it. - ▸
System.console()returns aConsolewithreadLineandreadPassword(which doesn't echo the characters), but it isnullwhen there is no interactive terminal, for example in IDE consoles or when input is redirected. Java 25 addedjava.lang.IOwithIO.readln(prompt)for simple programs, alongside compact source files (Topic 0.3).
Remember this
- 1
Create one with
Scanner in = new Scanner(System.in);afterimport java.util.Scanner;.System.inis the program's standard input, anInputStreamof raw bytes from the keyboard. Scanner turns those bytes into characters and the characters into tokens: pieces of text separated by whitespace (spaces, tabs, line breaks), which is Scanner's default delimiter. - 2
Token methods:
next()returns the next token as a String,nextInt(),nextLong(),nextDouble()andnextBoolean()read the next token and convert it. They skip any whitespace first, so42reads as42, and numbers on one line or on separate lines work the same way.nextLine()is different: it returns everything up to the end of the current line (without the line break) and moves past it. - 3
Every
next...call blocks: the program waits until the user has typed enough and pressed Enter. If the token doesn't match,nextIntthrowsInputMismatchExceptionand leaves the bad token in place; if the input has ended, it throwsNoSuchElementException. ThehasNextInt(),hasNextDouble(),hasNext()andhasNextLine()methods look ahead without consuming anything, so you can check first and react. - 4
The classic trap:
nextInt()reads25but leaves the Enter key's line break behind. A followingnextLine()finds that empty rest-of-line and returns""immediately, so the user never gets to type their name. Fix it by callingnextLine()once to throw the rest away, or by reading every line withnextLine()and converting withInteger.parseInt(line.strip())(Topic 1.6). - 5
Numbers are read using the default locale: on a German system
nextDouble()expects1,45, not1.45. Callin.useLocale(Locale.US)when the input format is fixed. Create one Scanner forSystem.inand reuse it; closing it also closesSystem.in, after which no part of the program can read the keyboard again. - 6
Scannercan read from other sources too:new Scanner("12 34")scans a fixed String (perfect for testing, and what this page's runnable examples do, because the browser has no keyboard), andnew Scanner(Path.of("data.txt"))scans a file (Phase 12). For very large inputs, such as programming contests,BufferedReaderis much faster (see the DSA course at/dsa).
Explain it without notes
What is a token, and how does nextInt() decide where one ends?
Explain why nextLine() after nextInt() returns an empty String, and give two fixes.
What is the difference between hasNextInt() and nextInt(), and why does a retry loop need next()?
Why should a program create only one Scanner for System.in, and why not close it?
Practice
Using new Scanner("7 3"), read two integers and print their sum, difference, product and integer quotient on separate labelled lines.
Using new Scanner("Meera\n14\n"), read a name with nextLine() and an age, and print Meera will be 18 in 4 years. Read the age the robust way (whole line plus parseInt).
Using new Scanner("5 -2 abc 9 0 4.5 3"), add up only the valid integers and print how many tokens were skipped.
Trade-offs
- ↔
Scanner's typed methods (
nextInt,nextDouble) are convenient and validate input, but they are slow and their mix withnextLineis error-prone; reading whole lines and parsing them yourself is more predictable. - ↔
BufferedReaderis fast and reports I/O errors, but gives you only lines; you split and convert them yourself. - ↔
Command-line arguments (the
argsarray ofmain) suit values known when the program starts and scripts; interactive input suits programs that talk to a person.
Done when you can
I can create a Scanner for the keyboard and for a fixed String, with the right import.
I can read Strings, ints, doubles and booleans and explain what a token is.
I can explain and fix the
nextIntthennextLinetrap.I validate input with
hasNextIntand discard bad tokens withnext.I know why to use one Scanner for
System.inand not close it.I can recognise
InputMismatchExceptionandNoSuchElementExceptionand say what caused each.