Java Scanner Handbook
1. Quick Summary
Scanner 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 (default is whitespace).
Package:
java.util.ScannerKey Feature: Easy parsing of primitives (
int,double, etc.) without manualInteger.parseInt().Performance: Slower than
BufferedReaderdue to regex parsing logic.Thread Safety: Not thread-safe.
2. Common Constructors
// 1. Reading from Console (Standard Input)
Scanner sc = new Scanner(System.in);
// 2. Reading from a File
Scanner sc = new Scanner(new File("input.txt"));
// 3. Reading from a String (Simulating input)
Scanner sc = new Scanner("10 20 30");3. Essential Methods Cheat Sheet
Method | Return Type | Description |
|---|---|---|
|
| Reads the next token (word) up to whitespace. |
|
| Reads the entire remaining line (including spaces). |
|
| Scans the next token as an |
|
| Scans the next token as a |
|
| Checks if there is another token. |
|
| Checks if the next token is a valid integer (useful for validation). |
|
| Changes the separator (e.g., to |
4. The "nextLine()" Trap (CRITICAL)
A very common bug occurs when you mix next()/nextInt() with nextLine().
The Problem:nextInt() reads the number but leaves the newline character (\n) in the buffer. The subsequent nextLine() reads that leftover newline and consumes it immediately, appearing to skip input.
The Fix:Fire an extra nextLine() to consume the leftover newline.
int age = sc.nextInt();
sc.nextLine(); // Consume the leftover newline
String name = sc.nextLine(); // Now works as expected5. Scanner vs. BufferedReader
Feature | Scanner | BufferedReader |
|---|---|---|
Parsing | Built-in ( | Manual ( |
Buffer Size | Small (1KB) | Large (8KB) |
Delimiter | Configurable (Regex) | Strictly Line-based |
Exceptions | Hides | Throws |
Best For | Console input, Parsing structured text | Reading massive files, Network streams |
6. Implementation Tips
Input Validation: Always use
hasNextInt()beforenextInt()to preventInputMismatchExceptionif the user types "abc" instead of "123".Closing: Always close Scanners attached to Files. Be careful closing System.in: closing it prevents your application from reading from the console again for its entire lifetime.
import java.util.Scanner;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
/**
* A comprehensive demonstration of Scanner usages.
* Includes:
* 1. Handling the "nextLine" trap.
* 2. Input validation (preventing crashes).
* 3. Reading from a file.
* 4. Using custom delimiters (CSV parsing).
*/
public class ScannerExamples {
public static void main(String[] args) {
// SETUP: Create a dummy file for the demonstration
createDummyFile("scores.txt");
System.out.println("=== 1. The Common 'nextLine' Trap ===");
demonstrateTrap();
System.out.println("\n=== 2. Input Validation (Robust Input) ===");
// Uncomment to run interactively, commented out for automated demo flow
// validateInputExample();
System.out.println("(Skipped interactive demo to keep output clean)");
System.out.println("\n=== 3. Reading from File ===");
readFromFile("scores.txt");
System.out.println("\n=== 4. Custom Delimiters (CSV Parsing) ===");
parseCSVString();
}
/**
* Pattern 1: Solving the problem where nextInt() leaves a newline character
* that causes the following nextLine() to be skipped.
*/
private static void demonstrateTrap() {
String input = "25\nJohn Doe"; // Simulated user input: Age then Name
Scanner sc = new Scanner(input);
System.out.println("Input Stream: " + input.replace("\n", "\\n"));
// Step 1: Read number
int age = sc.nextInt();
System.out.println("Read Age: " + age);
// Step 2: THE FIX
// If we don't do this, 'name' will be empty because it reads the leftover \n
sc.nextLine();
System.out.println("[Log] Consumed leftover newline");
// Step 3: Read Line
String name = sc.nextLine();
System.out.println("Read Name: " + name);
sc.close();
}
/**
* Pattern 2: Reading from a file safely.
* Note: Unlike BufferedReader, Scanner doesn't throw checked IOExceptions
* everywhere, but the constructor does.
*/
private static void readFromFile(String filename) {
try {
File file = new File(filename);
Scanner fileScanner = new Scanner(file);
while (fileScanner.hasNextLine()) {
String line = fileScanner.nextLine();
System.out.println("File Line: " + line);
}
fileScanner.close();
} catch (FileNotFoundException e) {
System.err.println("File not found: " + e.getMessage());
}
}
/**
* Pattern 3: Using delimiters to parse specific formats (like CSV).
*/
private static void parseCSVString() {
String csvData = "Apple,Banana,Cherry,Date";
Scanner sc = new Scanner(csvData);
// Set delimiter to comma
sc.useDelimiter(",");
while (sc.hasNext()) {
System.out.println("Token: " + sc.next());
}
sc.close();
}
/**
* Pattern 4: Validating input loop.
* Keeps asking until user enters a valid integer.
*/
private static void validateInputExample() {
Scanner console = new Scanner(System.in);
System.out.print("Enter an integer: ");
// Check if the next token is an integer BEFORE reading it
while (!console.hasNextInt()) {
String badInput = console.next(); // Consume the bad input
System.out.println("That's not a number! You typed: " + badInput);
System.out.print("Try again. Enter an integer: ");
}
int number = console.nextInt();
System.out.println("Success! You entered: " + number);
// Note: We usually do NOT close System.in scanners
}
// Helper method to create a dummy file
private static void createDummyFile(String filename) {
try (FileWriter writer = new FileWriter(filename)) {
writer.write("Player1 Score: 100\n");
writer.write("Player2 Score: 250\n");
writer.write("Player3 Score: 50");
} catch (IOException e) {
System.err.println("Setup failed: " + e.getMessage());
}
}
}
Analyze the following code snippet. If the input is '42' followed by a newline and then 'Java', what will be the value of the variable 'text'?
Scanner sc = new Scanner(System.in);int num = sc.nextInt();String text = sc.nextLine();
The answer: An empty string ""
nextInt() reads the number but leaves the newline character in the buffer; nextLine() immediately reads that remaining newline as an empty line.
nextInt() (or next(), nextDouble(), etc.) with nextLine() in Java's Scanner class. nextInt()and similar methods:Methods likenextInt(),next(),nextDouble()are designed to read specific data types (integers, tokens, doubles) and stop before consuming the newline character (\n) that is typically entered after the input by the user pressing the Enter key. This newline character remains in the input buffer.nextLine():ThenextLine()method, in contrast, reads the entire line of input, including any whitespace characters, until it encounters and consumes a newline character.
nextInt() and then immediately call nextLine(), the nextLine() method finds the leftover newline character in the buffer from the previous nextInt() call. It interprets this leftover newline as the entire line of input and returns an empty string, effectively "skipping" the expected user input for that nextLine() call. nextInt() (or other nextX() methods) and before calling nextLine(). This is typically done by adding an extra, empty nextLine() call: import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an integer: ");
int number = scanner.nextInt();
// Consume the leftover newline character
scanner.nextLine();
System.out.print("Enter a string: ");
String text = scanner.nextLine();
System.out.println("You entered: " + number + " and " + text);
scanner.close();
}
}scanner.nextLine(); after nextInt() reads and discards the newline character, ensuring that the subsequent scanner.nextLine(); correctly waits for and reads the user's string input.