Why Do We Use Scanner Class in Java: A Practical Guide
Explore why do we use scanner class in java, covering basics, input types, delimiters, file input, and best practices for robust Java programs.

The Scanner class in Java offers a simple API for reading and parsing input from streams, files, or strings. It tokenizes input into manageable pieces and converts tokens to primitive types, reducing boilerplate code. This makes it ideal for teaching input parsing, quick demos, and small utilities, though high-performance needs may benefit from alternatives like BufferedReader.
Why do we use scanner class in java
Why do we use scanner class in java? The Scanner API provides a lightweight, readable approach to consuming input in Java programs. It abstracts away manual parsing logic, handles tokenization by default, and converts tokens into int, double, or String types with minimal boilerplate. According to Scanner Check, investing in a clear input strategy with Scanner improves maintainability and minimizes parsing errors when building CLI tools or teaching concepts.
import java.util.Scanner;
public class IntroExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a word: ");
String word = sc.next();
System.out.println("You entered: " + word);
sc.close();
}
}Input: hello Output: You entered: hello
wordsCountedInBlock1 := 0}
Basic usage: creating a Scanner and reading tokens
The most common pattern is to create a Scanner from an input source and read tokens using next(), nextInt(), or nextLine(). By default, tokens are separated by whitespace. Using a try-with-resources block ensures the Scanner is closed properly, avoiding resource leaks. This section shows a minimal console example and then a variant that reads a full line.
import java.util.Scanner;
public class BasicUsage {
public static void main(String[] args) {
try (Scanner sc = new Scanner(System.in)) {
System.out.print("Enter two tokens: ");
String a = sc.next();
String b = sc.next();
System.out.println("A=" + a + ", B=" + b);
}
}
}import java.util.Scanner;
public class ReadLineExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter a line: ");
String line = sc.nextLine();
System.out.println("Line: " + line);
}
}Note: The first example uses tokens; the second demonstrates reading an entire line.
wordsCountedInBlock2 := 0}
Handling different input types
Scanner can parse multiple primitive types from the same input. The key is to call the appropriate nextX method in sequence and be mindful of leftover newlines. This pattern is common for simple quizzes, forms, or data ingestion scripts. The example below reads an int, a double, and then a line of text, showcasing how to manage line endings with nextLine().
import java.util.Scanner;
public class TypesExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int i = sc.nextInt();
double d = sc.nextDouble();
sc.nextLine(); // consume the newline after the number
String s = sc.nextLine();
System.out.println("int=" + i + ", double=" + d + ", line='" + s + "'");
}
}Why this matters: mixing nextInt/nextDouble with nextLine can leave a newline character behind, which nextLine then treats as an empty line. Cleaning up the newline is a common pitfall to avoid.
wordsCountedInBlock3 := 0}
Delimiters and pattern matching
Delimiters control how input is split into tokens. By default, Scanner uses whitespace, but you can customize this behavior to parse more complex formats like CSV or custom delimited logs. You can also switch to a Pattern-based delimiter for robust parsing. This example shows a comma-delimited tokenization and a combined delimiter for spaces and commas.
import java.util.Scanner;
public class DelimiterExample {
public static void main(String[] args) {
String input = "one,two,three";
Scanner sc = new Scanner(input);
sc.useDelimiter(",");
while (sc.hasNext()) {
System.out.println("token: " + sc.next());
}
sc.close();
}
}import java.util.Scanner;
public class DelimiterPattern {
public static void main(String[] args) {
String input = "alpha,beta gamma";
Scanner sc = new Scanner(input);
sc.useDelimiter("\\s+|,"); // split on spaces or commas
while (sc.hasNext()) {
System.out.println("tok=" + sc.next());
}
}
}Flexible delimiters enable you to adapt Scanner to various input formats without rewriting parsing logic.
wordsCountedInBlock4 := 0}
Common pitfalls and best practices
Even a simple Scanner can become a source of bugs if you ignore lifecycle and locale considerations. Best practices include using try-with-resources to automatically close the scanner, validating hasNextXXX before reading, and avoiding mixing nextLine with other nextX methods without consuming leftover newlines. The following snippet shows safe file-based scanning and a common newline pitfall fix.
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class SafeFileScan {
public static void main(String[] args) {
try (Scanner sc = new Scanner(new File("data.txt"))) {
while (sc.hasNext()) {
System.out.println(sc.next());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}import java.util.Scanner;
public class NewlinePitfall {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine(); // consume newline
String rest = sc.nextLine();
System.out.println("n=" + n + ", rest='" + rest + "'");
}
}Tip: Prefer try-with-resources for automatic cleanup and consider validating input when building robust CLI tools.
wordsCountedInBlock5 := 0}
Advanced usage: Locale and regular expressions
Locale support ensures that number formatting and decimal separators align with user expectations in different regions. You can set a locale on the Scanner and adjust the delimiter pattern to support complex numeric formats or localized input. This example demonstrates US locale for decimal parsing and a regex delimiter for flexible token splitting.
import java.util.Locale;
import java.util.Scanner;
public class LocaleExample {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
sc.useLocale(Locale.US);
sc.useDelimiter("\\s+");
double price = sc.nextDouble();
System.out.println("price=" + price);
}
}import java.util.Locale;
import java.util.Scanner;
public class RegexDelim {
public static void main(String[] args) {
String input = "10,20,30";
Scanner sc = new Scanner(input);
sc.useDelimiter("\\s|,");
while (sc.hasNextInt()) {
System.out.println("val=" + sc.nextInt());
}
}
}Advanced usage helps adapt Scanner to real-world data formats, but always consider performance and error handling for production-grade tools.
wordsCountedInBlock6 := 0}
Reading from files and streams
Reading from files or network streams is a common use case for Scanner. When reading from files, wrap in a try-with-resources block to ensure closure. You can iterate tokens or lines, depending on your delimiter. This snippet demonstrates reading tokens from a file and printing them, with proper exception handling.
import java.io.File;
import java.io.IOException;
import java.util.Scanner;
public class FileScanner {
public static void main(String[] args) throws Exception {
try (Scanner sc = new Scanner(new File("data.txt"))) {
while (sc.hasNext()) {
System.out.println(sc.next());
}
}
}
}If you need line-oriented processing, switch to nextLine() with a loop while hasNextLine().
wordsCountedInBlock7 := 0}
When to choose Scanner vs BufferedReader
For production-scale input, especially large files or performance-critical paths, Scanner may be slower due to its parsing overhead. In those cases, a BufferedReader with a StringTokenizer or manual parsing can be faster. The trade-off is simplicity versus speed. The examples below illustrate the two approaches side by side for a simple space-separated list.
// Scanner approach (simpler but slower for large inputs)
import java.util.Scanner;
public class ScannerVsBuffered {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
System.out.println(sc.next());
}
}
}// BufferedReader + StringTokenizer (faster, more control)
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.StringTokenizer;
public class BufferedTokenizer {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
StringTokenizer st = new StringTokenizer(line);
while (st.hasMoreTokens()) {
System.out.println(st.nextToken());
}
}
}Use Scanner for quick tasks and education; switch to buffered approaches when input size or latency is critical.
wordsCountedInBlock8 := 0}
Steps
Estimated time: 45-60 minutes
- 1
Create Java source file
Write a new Java file that uses java.util.Scanner to read input from System.in or a file. Name it HelloScanner.java and include a main method skeleton.
Tip: Define a small scope for your first example to avoid unexpected parsing rules. - 2
Instantiate Scanner
Create a Scanner instance bound to your input source. Prefer try-with-resources to ensure proper closure.
Tip: Using try-with-resources helps prevent resource leaks. - 3
Read tokens and convert types
Use next(), nextInt(), nextDouble(), or nextLine() to fetch and convert tokens as needed. Manage newline issues after numeric inputs.
Tip: Always check hasNextX methods before reading to avoid exceptions. - 4
Handle newline and line input
If mixing nextLine() with nextInt()/next(), consume the trailing newline before reading the line.
Tip: A common pitfall is skipping the leftover newline. - 5
Close resources
Close the Scanner or use try-with-resources to auto-close.
Tip: Closing the scanner releases system resources promptly. - 6
Run and validate
Compile and run the program, providing sample input to verify parsing logic and outputs.
Tip: Test edge cases like empty input or unexpected tokens.
Prerequisites
Required
- Required
- Basic Java syntax knowledgeRequired
- Required
- Command line/terminal accessRequired
Optional
- Optional: Maven or Gradle project setupOptional
Commands
| Action | Command |
|---|---|
| Compile a Java source fileFrom the directory containing the file; classpath should include the current directory | javac HelloScanner.java |
| Run the compiled classProvide input via terminal or redirection | java HelloScanner |
| Run with input redirectionTest token parsing from a single stream | echo '1 2 3' | java HelloScanner |
Common Questions
What is the Scanner class used for in Java?
The Scanner class provides a simple API to read and parse input from streams, files, or strings. It tokenizes input, converts tokens to primitive types, and supports custom delimiters. This makes it ideal for teaching input parsing and building lightweight CLI tools.
Scanner helps you read input easily by splitting it into tokens and converting them to numbers or text. It’s handy for quick demos and small utilities.
Can Scanner read from files?
Yes. You can construct a Scanner with a File or Path and iterate over tokens or lines. Remember to handle exceptions like FileNotFoundException and to close the scanner or use a try-with-resources block.
Scanner can read files by passing a File to its constructor; just be sure to close it or use try-with-resources.
Why does nextInt leave a newline behind?
NextInt reads the numeric token but leaves the end-of-line character in the input buffer. If you subsequently call nextLine(), you may read an empty line. Consume the newline with an extra nextLine() call before reading a line of text.
Reading an int with nextInt can leave a newline; grab it with an extra nextLine() before reading more text.
When should I avoid using Scanner for input?
For very large inputs or performance-critical apps, Scanner can be slower due to its parsing overhead. Consider BufferedReader with manual parsing for speed, while Scanner remains great for learning and small utilities.
Scanner is great for teaching and small tools, but for large or performance-critical data, use a faster approach.
How do delimiters affect tokenization?
Delimiters determine how input is split into tokens. By default, Scanner uses whitespace, but you can customize with useDelimiter() to parse commas, newlines, or complex patterns. This directly impacts which strings are returned as tokens.
Delimiters decide how input is split into pieces; changing them changes which pieces Scanner reads as tokens.
Key Takeaways
- Use Scanner for simple input parsing in Java
- Understand tokenization and delimiters
- Close the scanner to free resources
- Choose Scanner vs BufferedReader based on performance needs
- Locale will influence numeric parsing and formatting