Java Scanner
last modified July 18, 2026
In this article we show how to read and parse input in Java using
java.util.Scanner.
The Scanner class in Java is a simple text scanner that can parse primitive types and strings using regular expressions. It breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
The Scanner class is commonly used for:
- Reading user input from the console
- Parsing data from files
- Extracting values from strings
- Processing structured text data such as CSV
- Reading input with custom delimiter patterns
The scanner can read from various input sources including
InputStream, File, Path,
Readable, and String.
While Scanner is versatile, other classes may be better suited for specific tasks:
- BufferedReader — More efficient for reading large text files line by line. It buffers input for better performance and is preferred when raw line reading without parsing is needed.
- Files.readString / Files.readAllLines — Simpler for reading entire small files into a single string or a list of lines in one call.
- Stream API (Files.lines) — Enables functional-style processing of file lines with operations such as filtering, mapping, and collecting.
- Console — More convenient for reading passwords (without echoing) and formatted prompts from the console.
- DataInputStream / ObjectInputStream — Designed for reading binary data and deserializing Java objects, not text.
- String.split / Pattern — Lighter alternatives when only simple string splitting or regex matching is needed without the overhead of a Scanner object.
Reading user input
The most common use of Scanner is reading user input from the standard
input stream (System.in).
void main() {
var scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
var name = scanner.nextLine();
System.out.print("Enter your age: ");
var age = scanner.nextInt();
System.out.printf("Hello %s, you are %d years old%n", name, age);
}
The nextLine method reads a line of text, while
nextInt reads an integer value. The Scanner automatically
handles the conversion from text to the requested type.
$ java Main.java Enter your name: John Enter your age: 34 Hello John, you are 34 years old
Reading different data types
The Scanner provides methods for reading various primitive types and
common data types. Each method has a corresponding
hasNextXxx method for checking availability.
void main() {
var scanner = new Scanner(System.in);
System.out.print("Enter an integer: ");
if (scanner.hasNextInt()) {
var i = scanner.nextInt();
System.out.printf("Integer: %d%n", i);
}
System.out.print("Enter a double: ");
if (scanner.hasNextDouble()) {
var d = scanner.nextDouble();
System.out.printf("Double: %.2f%n", d);
}
System.out.print("Enter a boolean: ");
if (scanner.hasNextBoolean()) {
var b = scanner.nextBoolean();
System.out.printf("Boolean: %b%n", b);
}
System.out.print("Enter a word: ");
var token = scanner.next();
System.out.printf("Token: %s%n", token);
}
The hasNextInt, hasNextDouble, and
hasNextBoolean methods check whether the next token
can be interpreted as the requested type, preventing
InputMismatchException.
$ java Main.java Enter an integer: 42 Integer: 42 Enter a double: 3.14 Double: 3.14 Enter a boolean: true Boolean: true Enter a word: hello Token: hello
Reading from a file
The Scanner can read input directly from a file, line by line or token by token.
Bratislava 25.3 Prague 18.7 Vienna 22.1 Budapest 20.5 Warsaw 16.8
void main() throws Exception {
try (var scanner = new Scanner(new File("temperatures.txt"))) {
while (scanner.hasNextLine()) {
var line = scanner.nextLine();
System.out.println(line);
}
}
}
The hasNextLine method checks if there is another line
in the input. The try-with-resources statement ensures
that the scanner is properly closed after use.
$ java Main.java Bratislava 25.3 Prague 18.7 Vienna 22.1 Budapest 20.5 Warsaw 16.8
Parsing structured file data
We can combine token-reading methods with line-reading to parse structured data from files.
void main() throws Exception {
try (var scanner = new Scanner(new File("temperatures.txt"))) {
while (scanner.hasNext()) {
var city = scanner.next();
var temperature = scanner.nextDouble();
System.out.printf("%s: %.1f°C%n", city, temperature);
}
}
}
The next method reads the city name as a string token,
and nextDouble reads the temperature value. The default
whitespace delimiter separates the tokens correctly.
$ java Main.java Bratislava: 25.3°C Prague: 18.7°C Vienna: 22.1°C Budapest: 20.5°C Warsaw: 16.8°C
Reading from a string
The Scanner can also parse data directly from a string, which is useful for processing text data embedded in the application.
void main() {
var data = "apple 1.20 banana 0.80 cherry 2.50";
try (var scanner = new Scanner(data)) {
while (scanner.hasNext()) {
var fruit = scanner.next();
var price = scanner.nextDouble();
System.out.printf("%s: $%.2f%n", fruit, price);
}
}
}
The string is parsed token by token. The Scanner iterates through the text, extracting alternating string and double values.
$ java Main.java apple: $1.20 banana: $0.80 cherry: $2.50
Custom delimiters
The useDelimiter method sets a custom delimiter pattern
for tokenizing the input. This is useful for parsing non-whitespace
separated data.
void main() {
var data = "10,20,30,40,50";
try (var scanner = new Scanner(data)) {
scanner.useDelimiter(",");
var sum = 0;
while (scanner.hasNextInt()) {
sum += scanner.nextInt();
}
System.out.printf("Sum: %d%n", sum);
}
}
The delimiter is set to a comma with useDelimiter(","),
allowing the Scanner to parse comma-separated integer values.
$ java Main.java Sum: 150
Reading CSV data
A more realistic CSV parsing example demonstrates reading structured tabular data from a file.
John Doe,Software Engineer,75000 Jane Smith,Data Analyst,68000 Robert Brown,DevOps Engineer,82000 Emily Davis,Product Manager,79000
void main() throws Exception {
try (var scanner = new Scanner(new File("employees.csv"))) {
while (scanner.hasNextLine()) {
var line = scanner.nextLine();
try (var lineScanner = new Scanner(line)) {
lineScanner.useDelimiter(",");
var name = lineScanner.next();
var position = lineScanner.next();
var salary = lineScanner.nextInt();
System.out.printf("%-20s %-20s $%d%n",
name, position, salary);
}
}
}
}
Each line is read with nextLine, then a secondary Scanner
parses the comma-separated fields. This nested approach handles CSV
data cleanly and is easy to adapt for different formats.
$ java Main.java John Doe Software Engineer $75000 Jane Smith Data Analyst $68000 Robert Brown DevOps Engineer $82000 Emily Davis Product Manager $79000
Finding patterns with findInLine
The findInLine method searches for a pattern in the
current line without advancing past the line terminator.
void main() {
var data = """
Name: John Doe Age: 34 City: Bratislava
Name: Jane Doe Age: 28 City: Prague
""";
try (var scanner = new Scanner(data)) {
while (scanner.hasNextLine()) {
var name = scanner.findInLine("Name: (\\w+\\s+\\w+)");
var age = scanner.findInLine("Age: (\\d+)");
var city = scanner.findInLine("City: (\\w+)");
if (name != null) {
System.out.printf("%s, %s, %s%n",
name.replace("Name: ", ""), age, city);
}
if (scanner.hasNextLine()) {
scanner.nextLine();
}
}
}
}
The findInLine method applies a regular expression to the
current line and returns the matched text, or null if no
match is found.
$ java Main.java John Doe, Age: 34, City: Bratislava Jane Doe, Age: 28, City: Prague
Using Locale-aware scanning
The useLocale method configures locale-specific formatting
for parsing numbers, such as decimal separators.
import java.util.Locale;
void main() {
var data = "3.14 2,718 1,5";
try (var scanner = new Scanner(data)) {
// default locale uses dot as decimal separator
scanner.useLocale(Locale.US);
System.out.printf("US: %.2f%n", scanner.nextDouble());
System.out.printf("US: %.2f%n", scanner.nextDouble());
// German locale uses comma as decimal separator
scanner.useLocale(Locale.GERMAN);
System.out.printf("DE: %.2f%n", scanner.nextDouble());
}
}
The Locale.US interprets the dot as a decimal separator,
while Locale.GERMAN uses the comma. This is important
when parsing internationalized data.
$ java Main.java US: 3.14 US: 2.72 DE: 1.50
The skip method
The skip method skips input that matches a given pattern,
useful for ignoring headers or unwanted sections.
void main() {
var data = """
=== Data Start ===
10 20 30
40 50 60
=== Data End ===
""";
try (var scanner = new Scanner(data)) {
// skip the header line
scanner.skip("=== Data Start ===\\s*");
while (scanner.hasNextInt()) {
var value = scanner.nextInt();
System.out.printf("%d ", value);
}
System.out.println();
}
}
The skip method discards the header line, allowing the
Scanner to proceed directly to parsing the numeric data.
$ java Main.java 10 20 30 40 50 60
Reading with radix
The useRadix method sets the default radix for
interpreting numeric values. This is useful for parsing hexadecimal,
octal, or binary numbers.
void main() {
var hexData = "FF A0 1C 4B";
try (var scanner = new Scanner(hexData)) {
scanner.useRadix(16);
while (scanner.hasNextInt()) {
var value = scanner.nextInt();
System.out.printf("%d ", value);
}
System.out.println();
}
}
With radix set to 16, the Scanner interprets hexadecimal values
such as FF as decimal 255.
$ java Main.java 255 160 28 75
Handling InputMismatchException
When input does not match the expected type, the Scanner throws
InputMismatchException. Proper exception handling
ensures robust applications.
void main() {
var data = "42 abc 3.14";
try (var scanner = new Scanner(data)) {
while (scanner.hasNext()) {
try {
if (scanner.hasNextInt()) {
System.out.printf("Int: %d%n", scanner.nextInt());
} else if (scanner.hasNextDouble()) {
System.out.printf("Double: %.2f%n", scanner.nextDouble());
} else {
System.out.printf("Token: %s%n", scanner.next());
}
} catch (InputMismatchException e) {
System.out.printf("Error parsing: %s%n", scanner.next());
}
}
}
}
The safest approach is to use hasNextXxx methods before
calling the corresponding nextXxx methods, avoiding
exceptions altogether.
$ java Main.java Int: 42 Token: abc Double: 3.14
Scanner tokens and streams
The tokens method returns a stream of tokens, enabling
functional-style processing of scanner input.
Word frequency counter
The following example tokenizes a sentence and counts how many times
each word appears, using Collectors.groupingBy with
Collectors.counting.
void main() {
var data = "the sun is bright the moon is pale the grass is green";
try (var scanner = new Scanner(data)) {
scanner.tokens()
.map(String::toLowerCase)
.collect(Collectors.groupingBy(
word -> word, TreeMap::new, Collectors.counting()))
.forEach((word, count) ->
System.out.printf("%-12s %d%n", word, count));
}
}
The tokens method converts the scanner's input into a
Stream<String>. We map each token to lowercase
and collect the stream into a TreeMap that groups words
and counts their occurrences. The result is printed in alphabetical
order.
$ java Main.java bright 1 grass 1 green 1 is 3 moon 1 pale 1 sun 1 the 3
Filtering and transforming tokens
In this example we parse city-temperature pairs and filter cities whose temperature exceeds 20°C, format the output, and display them in sorted order.
void main() {
var data = "Bratislava 25.3 Prague 18.7 Vienna 22.1 Budapest 20.5";
try (var scanner = new Scanner(data)) {
var tokens = scanner.tokens().toList();
var warmCities = IntStream.range(0, tokens.size())
.filter(i -> i % 2 == 1)
.filter(i -> Double.parseDouble(tokens.get(i)) > 20)
.mapToObj(i -> "%s: %.1f\u00b0C".formatted(
tokens.get(i - 1), Double.parseDouble(tokens.get(i))))
.sorted()
.toList();
warmCities.forEach(System.out::println);
}
}
We collect all tokens into a list, then use IntStream.range
to work with index positions. The odd indices contain temperatures;
we filter those above 20, format city-temperature pairs, and sort
the results.
$ java Main.java Bratislava: 25.3°C Budapest: 20.5°C Vienna: 22.1°C
Grouping and summarizing numeric data
This example reads alternating department-salary pairs and computes the average salary for each department.
void main() {
var data = "IT 45000 IT 52000 HR 38000 HR 41000 IT 49000 HR 39500";
try (var scanner = new Scanner(data)) {
var tokens = scanner.tokens().toList();
var depts = new TreeMap<>(IntStream.range(0, tokens.size())
.filter(i -> i % 2 == 0)
.boxed()
.collect(Collectors.groupingBy(
i -> tokens.get(i),
Collectors.averagingDouble(
i -> Double.parseDouble(tokens.get(i + 1))))));
depts.forEach((dept, avg) ->
System.out.printf("%s: $%.2f%n", dept, avg));
}
}
Even indices hold department names, odd indices hold salaries. We
filter for even indices, group by department name, and compute the
average of the adjacent salary values using
Collectors.averagingDouble.
$ java Main.java HR: $38833.33 IT: $48666.67
Building a configuration map
Here we parse key-value pairs from a string and collect them into a
Map using Collectors.toMap.
void main() {
var data = "host localhost port 5432 user admin timeout 30";
try (var scanner = new Scanner(data)) {
var tokens = scanner.tokens().toList();
var config = IntStream.range(0, tokens.size() - 1)
.filter(i -> i % 2 == 0)
.boxed()
.collect(Collectors.toMap(
i -> tokens.get(i),
i -> tokens.get(i + 1)));
config.forEach((key, value) ->
System.out.printf("%s = %s%n", key, value));
}
}
Even indices contain keys and odd indices contain values. We use
IntStream.range to iterate indices, filter for even
positions, and collect the adjacent pairs into a map.
$ java Main.java host = localhost port = 5432 timeout = 30 user = admin
Source
Java Scanner - language reference
In this article we have used Java's Scanner class to
read and parse input data.
Author
List all Java tutorials.