Explore the ins and outs of Java Scanner – from diverse constructors to a multitude of methods. Delve into examples, compare Scanner vs BufferedReader, and grasp FAQs and vital considerations.
What is a Java Scanner?
The Scanner class in Java is part of the java.util
package. It is a tool for breaking down input into meaningful tokens. A token can be a single word, a number, or even a special character. The Scanner class can identify different types of tokens and convert them into appropriate data types.
A Java Scanner is like a smart detective that helps your program read different types of information, such as text or numbers, from various sources like the keyboard or files. It breaks down the input into smaller parts, making it easier for your program to understand and use the information.
Think of a Java Scanner as a listener that hears what someone types on the computer and helps your program understand it. It can be used in many situations, like when you want someone to type their name, a number, or even a sentence, and your program needs to do something with that information. For example, if you’re making a calculator, the Scanner can listen to the numbers someone types and do the math. Or if you’re making a chatbot, the Scanner can listen to what a person types and respond based on that. It’s handy whenever you need your program to interact with someone typing things in.
Java Scanner Use Cases
Here are a few situations where Java Scanner can be useful:
- User Input: Taking inputs from a user during a program’s execution, like asking for a name, age, or any information required for the program to proceed.
- File Reading: Extracting information from files, such as reading a text file to process its contents.
- Data Parsing: Breaking down a string of text or data into smaller parts, like separating words or numbers from a sentence.
- Tokenization: Analyzing input and splitting it into individual pieces or tokens for further processing, like breaking down a sentence into words.
- Menu Selection: For programs with menus where users make choices by inputting a number or specific keywords.
- Data Validation: Verifying if the input matches certain criteria, like ensuring an entered value is a number or within a specific range.
- Simple Games: Creating text-based games where players input commands or choices to progress.
- Database Interaction: When creating programs that read input to query databases or store information.
Creating a Scanner Object
A Java scanner can be created by passing an input source to its constructor. The input source can be a System.in
object, which represents the standard input stream, a File
object, which represents a file on the disk, or a String
object, which represents a string literal.
For example, to create a scanner that reads from the user input, we can write:
Scanner sc = new Scanner(System.in); // Create a scanner object
JavaTo create a scanner that reads from a file, we can write:
File file = new File("input.txt"); // Create a file object
Scanner sc = new Scanner(file); // Create a scanner object
JavaTo create a scanner that reads from a string, we can write:
String str = "Hello, world!"; // Create a string object
Scanner sc = new Scanner(str); // Create a scanner object
JavaHow to Use Java Scanner Methods?
A Java scanner provides various methods to read and parse different types of data from the input source. Some of the most commonly used methods are:
next()
: This method returns the next token as a String object. It only reads until the first delimiter, so it can be used to read a single word from the input.
nextLine()
: This method returns the next line of input as a String object. It reads until the end of the line, so it can be used to read a whole sentence or paragraph from the input.
nextInt()
: This method returns the next token as an int value. It parses the token as an integer, so it can be used to read a numerical value from the input. It throws an InputMismatchException if the token cannot be parsed as an integer.
nextDouble()
: This method returns the next token as a double value. It parses the token as a double-precision floating-point number, so it can be used to read a decimal value from the input. It throws an InputMismatchException if the token cannot be parsed as a double.
Similarly, there are other methods to read and parse other primitive data types, such as nextBoolean()
, nextByte()
, nextFloat()
, nextLong()
, and nextShort()
.
Example: Let’s consider a scenario of a job application where a candidate’s details are collected using Scanner methods:
import java.util.Scanner;
public class JobApplication {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Create a scanner object
System.out.println("Welcome! Please enter your details for the job application:");
// Name input
System.out.print("Enter your full name: ");
String name = scanner.nextLine();
// Age input
System.out.print("Enter your age: ");
int age = scanner.nextInt();
// Salary expectation input
System.out.print("Enter your expected salary: ");
double salary = scanner.nextDouble();
// Boolean - Relocation availability input
System.out.print("Are you open to relocation? (true/false): ");
boolean willingToRelocate = scanner.nextBoolean();
// Byte - Years of experience input
System.out.print("Years of professional experience: ");
byte yearsOfExperience = scanner.nextByte();
// Float - GPA input
System.out.print("Enter your GPA: ");
float gpa = scanner.nextFloat();
// Long - Contact number input
System.out.print("Enter your contact number: ");
long contactNumber = scanner.nextLong();
// Short - Number of languages spoken
System.out.print("How many languages do you speak? (0-32767): ");
short languagesSpoken = scanner.nextShort();
// Output candidate's entered details
System.out.println("Name: " + name);
System.out.println("Age: " + age);
System.out.println("Salary Expectation: " + salary);
System.out.println("Willing to Relocate: " + willingToRelocate);
System.out.println("Years of Experience: " + yearsOfExperience);
System.out.println("GPA: " + gpa);
System.out.println("Contact Number: " + contactNumber);
System.out.println("Languages Spoken: " + languagesSpoken);
scanner.close(); // Close the scanner
}
}
JobApplication.javaOutput:
Java Scanner Methods
Below is the table detailing the various methods available in the Java Scanner class for handling different types of input.
Sr. No. | Method | Description |
---|---|---|
1. | close() | Closes the scanner and releases any resources it was using. |
2. | delimiter() | Returns the pattern that the scanner uses to separate tokens. A token is a piece of data that the scanner can read. |
3. | findAll(String pattern) | Returns a stream of results that match the given pattern. A stream is a sequence of data that can be processed one by one. |
4. | findInLine(String pattern) | Returns the next piece of data that matches the given pattern, but only within the current line of input. A line is a sequence of characters that ends with a newline character. |
5. | findWithinHorizon(String pattern, int horizon) | Returns the next piece of data that matches the given pattern, but only within a certain distance from the current position of the scanner. The distance is measured in characters. |
6. | hasNext() | Returns true if the scanner has more data to read, and false otherwise. |
7. | hasNextBigDecimal() | Returns true if the next piece of data that the scanner can read is a big decimal number, and false otherwise. A big decimal number is a very large or very precise number that can have many digits. |
8. | hasNextBigInteger() | Returns true if the next piece of data that the scanner can read is a big integer number, and false otherwise. A big integer number is a very large number that can have many digits. |
9. | hasNextBoolean() | Returns true if the next piece of data that the scanner can read is a boolean value, and false otherwise. A boolean value is either true or false. |
10. | hasNextByte() | Returns true if the next piece of data that the scanner can read is a byte value, and false otherwise. A byte value is a small number that can range from -128 to 127. |
11. | hasNextDouble() | Returns true if the next piece of data that the scanner can read is a double value, and false otherwise. A double value is a decimal number that can have up to 15 digits of precision. |
12. | hasNextFloat() | Returns true if the next piece of data that the scanner can read is a float value, and false otherwise. A float value is a decimal number that can have up to 7 digits of precision. |
13. | hasNextInt() | Returns true if the next piece of data that the scanner can read is an int value, and false otherwise. An int value is a whole number that can range from -2147483648 to 2147483647. |
14. | hasNextLine() | Returns true if the scanner has another line of input to read, and false otherwise. |
15. | hasNextLong() | Returns true if the next piece of data that the scanner can read is a long value, and false otherwise. A long value is a whole number that can range from -9223372036854775808 to 9223372036854775807. |
16. | hasNextShort() | Returns true if the next piece of data that the scanner can read is a short value, and false otherwise. A short value is a small number that can range from -32768 to 32767. |
17. | ioException() | Returns the last input/output exception that the scanner encountered, or null if none occurred. An input/output exception is an error that happens when reading or writing data. |
18. | locale() | Returns the locale that the scanner uses to interpret the input. A locale is a set of rules and preferences that define how data is formatted and displayed for a specific region or language. |
19. | match() | Returns the result of the last scanning operation that the scanner performed, or null if none occurred. A result contains information about the piece of data that the scanner read, such as its value, position, and pattern. |
20. | next() | Returns the next piece of data that the scanner can read as a string. A string is a sequence of characters. |
21. | nextBigDecimal() | Returns the next piece of data that the scanner can read as a big decimal number. |
22. | nextBigInteger() | Returns the next piece of data that the scanner can read as a big integer number. |
23. | nextBoolean() | Returns the next piece of data that the scanner can read as a boolean value. |
24. | nextByte() | Returns the next piece of data that the scanner can read as a byte value. |
25. | nextDouble() | Returns the next piece of data that the scanner can read as a double value. |
26. | nextFloat() | Returns the next piece of data that the scanner can read as a float value. |
27. | nextInt() | Returns the next piece of data that the scanner can read as an int value. |
28. | nextLine() | Returns the next line of input that the scanner can read as a string. |
29. | nextLong() | Returns the next piece of data that the scanner can read as a long value. |
30. | nextShort() | Returns the next piece of data that the scanner can read as a short value. |
31. | radix() | Returns the radix that the scanner uses to interpret the input. A radix is the base of a number system, such as 10 for decimal, 2 for binary, or 16 for hexadecimal. |
32. | remove() | Throws an exception if called. It is inherited from the Iterator interface, which the scanner implements. |
33. | reset() | Resets the scanner to its initial state, using the default delimiter, locale, and radix. |
34. | skip(String pattern) | Skips over any input that matches the given pattern, and returns the scanner itself. This can be useful to ignore some parts of the input that are not relevant or useful. |
35. | tokens() | Returns a stream of strings that are separated by the delimiter of the scanner. This can be useful to process the input in a functional way, using methods like map, filter, or reduce. |
36. | toString() | Returns a string representation of the scanner, which includes its input source, delimiter, locale, radix, and position. This can be useful for debugging purposes. |
37. | useDelimiter(Pattern pattern) | Modifies the scanner’s delimiting pattern to the specified pattern, enabling token separation based on the defined pattern. |
38. | useDelimiter(String pattern) | Adjusts the scanner’s delimiting pattern by constructing a pattern from the given String, facilitating token separation as per the pattern created. |
39. | useLocale(Locale locale) | Configures the scanner’s locale to the specified locale, allowing for the correct interpretation of localized data such as numbers, dates, and times. |
40. | useRadix(int radix) | Sets the scanner’s default radix to the specified radix, enabling proper conversion of numerical input based on the specified base. |
How to Check the Input Type and Availability?
Sometimes, we may want to check the type and availability of the next input before reading it. For example, we may want to check if the input has ended, or if the next input is of a certain type. For this purpose, we can use the hasNext()
and hasNextXYZ()
methods, where XYZ is the type we are interested in.
The hasNext()
method returns true if there is another token in the input and false otherwise. The hasNextXYZ()
method returns true if the next token can be parsed as a value of type XYZ, and false otherwise. For example, hasNextInt()
returns true if the next token can be parsed as an int value, and false otherwise.
Let’s consider a scenario where we want to analyze and process a sequence of user inputs that include different types of data like strings, integers, and decimals. For this, the below Java program processes a user-entered sequence of integers, doubles, or words. Upon encountering the input “exit”, it stops the input loop and calculates the sum of integers, the count of integers, the average of doubles, and the count of non-numeric inputs, displaying the collected data.
import java.util.Scanner;
public class DataProcessingExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in); // Create a scanner object
int intSum = 0, intCount = 0;
double doubleSum = 0.0;
int doubleCount = 0;
int stringCount = 0;
System.out.println("Enter a sequence of integers, doubles, or words (enter 'exit' to finish):");
while (scanner.hasNext()) { // Check if there is another token
if (scanner.hasNextInt()) { // Check if the next input is an integer
intSum += scanner.nextInt(); // Add integer to the sum
intCount++; // Increment the count for integers
} else if (scanner.hasNextDouble()) { // Check if the next input is a double
doubleSum += scanner.nextDouble(); // Add double to the sum
doubleCount++; // Increment the count for doubles
} else {
String input = scanner.next(); // Read the input as a String
if (input.equalsIgnoreCase("exit")) {
break; // Exit the loop if the input is 'exit'
}
stringCount++; // Increment the count for other inputs
}
}
System.out.println("Sum of integers: " + intSum); // Print the sum of integers
System.out.println("Count of integers: " + intCount); // Print the count of integers
System.out.println("Average of doubles: " + (doubleSum / doubleCount)); // Calculate and print the average of doubles
System.out.println("Count of words: " + stringCount); // Print the count of words
// Close the scanner (optional for the program to end)
scanner.close(); // Close the scanner
}
}
DataProcessingExample.java// Input
Enter a sequence of integers, doubles, or words (enter 'exit' to finish):
5 10.5 test 8 4 12.7 end exit
// Output
Sum of integers: 17
Count of integers: 3
Average of doubles: 11.6
Count of words: 2
CMDHandling Exceptions with Scanner in Java
In Java, the Scanner class provides built-in error-handling mechanisms to manage exceptions that might occur during input operations. These exceptions are a part of Java’s standard exception hierarchy and are crucial for ensuring smooth and robust program execution.
When using Scanner methods like nextInt()
, nextDouble()
, or nextLine()
, various issues could arise while interpreting input. The Scanner class handles these potential issues through two primary exceptions:
- InputMismatchException: This exception is triggered when the Scanner encounters input that doesn’t match the expected data type. For instance, if you’re trying to read an integer but the input is not a valid number, an InputMismatchException is raised.
- NoSuchElementException: This exception occurs when a Scanner method is used but there’s no more input to read. For instance, if you’re trying to fetch the next token in the input but there isn’t anything left, a NoSuchElementException is thrown.
To ensure smooth program flow and prevent unexpected crashes, developers can use error-handling mechanisms like try-catch blocks. By enclosing Scanner operations in a try block, they can catch and handle potential exceptions that might arise during the input process. This enables programmers to gracefully manage these errors without causing the program to abruptly halt.
Here’s an example of how you might use a try-catch block with a Scanner:
import java.util.Scanner;
import java.util.InputMismatchException;
public class ScannerErrorHandlingExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
try {
System.out.print("Enter a number: ");
int num = scanner.nextInt();
System.out.println("You entered: " + num);
} catch (InputMismatchException e) {
System.out.println("Invalid input! Please enter a valid number.");
}
}
}
ScannerErrorHandlingExample.javaIn this example, the try block attempts to read an integer using scanner.nextInt()
. If the user enters something that is not an integer, the InputMismatchException will be caught by the catch block, allowing the program to handle the error and continue execution gracefully.
By employing error-handling mechanisms like these, Scanner operations can be safeguarded, ensuring a more robust and fault-tolerant program.
How to Close a Scanner in Java?
Closing a Scanner in Java is essential to release resources and avoid potential memory leaks. The Scanner class provides the close()
method, which should be utilized to properly close the scanner and free up system resources. By invoking scanner.close()
, you ensure the proper termination of input operations and the release of associated resources, promoting efficient memory management in your Java programs.
Scanner vs Buffered Reader
Below, find a comparison highlighting the key distinctions between Scanner and BufferedReader in Java for input handling and processing.
Aspect | Scanner | BufferedReader |
---|---|---|
Purpose | Parsing data as tokens based on patterns. | Reading data without specialized interpretation. |
Data Sources | Reads from various sources (standard input stream, files, strings). | Reads only from character-input streams (e.g., files). |
Data Types | Parses different data types (int, decimal). | Reads text data as strings. |
Synchronization | Not synchronized, not thread-safe. | Synchronized and thread-safe. |
Buffer Size | Smaller buffer (1024 characters). | Larger buffer (8192 characters) for more efficiency. |
Things to Consider
Here are some key considerations when using the Java Scanner class:
- Resource Management: Always close the Scanner using the
close()
method to release system resources after its usage to prevent potential memory leaks. - Input Validation: Validate user input to handle unexpected or erroneous input using methods like
hasNextInt()
,hasNextDouble()
, oruseDelimiter()
to set specific delimiters. - Exception Handling: Utilize try-catch blocks to handle exceptions such as
NoSuchElementException
orInputMismatchException
that might arise from unexpected input scenarios. - Thread Safety: Scanner instances are not thread-safe. Avoid sharing Scanner instances across multiple threads concurrently to prevent synchronization issues.
- Memory Usage: Consider the memory impact when reading large files or continuous input streams, as the Scanner class might consume significant memory, impacting application performance.
- Input Buffering: When handling large amounts of input, consider using buffered readers for improved efficiency and performance compared to Scanner, especially in file or network input scenarios.
- Unicode and Locale Handling: Take into account the Unicode characters and locale settings when working with Scanner for internationalization and localization requirements.
- Delimiter Configurations: Carefully set delimiters to appropriately segment the input, ensuring accurate tokenization and data extraction.
- User Input Feedback: Provide clear and descriptive prompts for user input to guide and assist users in providing the expected input types.
- Input Sanitization: Implement input sanitization methods to remove unwanted characters or sanitize user inputs for security and data integrity.
- File Handling: For file input, verify file existence and permissions before initiating Scanner operations to prevent unexpected file-related exceptions.
- Scanner Reset: If reusing a Scanner for multiple input sources, ensure to reset it by closing and creating a new instance or using
scanner.reset()
if working with specific input streams.
FAQs
Is the Scanner class thread-safe?
No, Scanner instances are not thread-safe. Avoid sharing Scanner objects among multiple threads simultaneously.
When should we close a Scanner?
Close the Scanner using the close()
method when you’re finished with input operations to release system resources.
What happens if we call close () on an already closed Scanner?
Calling close()
on an already closed Scanner will not cause any exceptions or issues. It’s safe to call close()
multiple times.
How can we handle unexpected input when using a Scanner?
Use exception handling, such as try-catch blocks, to catch exceptions like InputMismatchException
or NoSuchElementException
.
Can we use a Scanner to read from files or input streams?
Yes, the Scanner can read from various input sources like files, InputStreams, or Strings using appropriate constructors.
How can we change the default delimiter used by Scanner?
Use the useDelimiter()
method to specify a custom delimiter pattern for tokenizing input.
Can a closed Scanner be reopened for further input operations?
Once a Scanner is closed, it cannot be reopened. Create a new instance for subsequent input operations.
What is the difference between next() and nextLine() methods in Java’s Scanner class?
next()
reads the next token until the first delimiter (by default, whitespace), whereas nextLine()
reads the entire line until the next line separator (newline character \n
).
What is the primary difference between hasNext() and hasNextLine() methods?
hasNext()
: This method checks whether there is another token available in the input, considering the presence of any valid input token separated by a delimiter (default is whitespace). It doesn’t consider the entire line, just the existence of the next token.hasNextLine()
: Contrarily,hasNextLine()
checks for the presence of another line in the input stream. It verifies whether the input includes another line separated by an end-of-line delimiter (\n
). It doesn’t analyze individual tokens but rather the entire line of input.
What happens if we try to use next() methods after closing the Scanner?
Using the next() methods after closing the Scanner will result in an IllegalStateException being thrown.
Conclusion
In conclusion, Java Scanner is used for efficiently handling user input across various sources, whether from the console, files, or strings. With its diverse methods for extracting tokens, converting data types, and customizable delimiters, the Scanner class offers a comprehensive solution for parsing and interpreting input data.
Learn More
Interested in learning more?
Check out our blog on Java 21: Instance Main Methods and Unnamed Classes
Top Picks for Learning Java
Explore the recommended Java books tailored for learners at different levels, from beginners to advanced programmers.
Disclaimer: The products featured or recommended on this site are affiliated. If you purchase these products through the provided links, I may earn a commission at no additional cost to you.
- All Levels Covered: Designed for novice, intermediate, and professional programmers alike
- Accessible Source Code: Source code for all examples and projects are available for download
- Clear Writing Style: Written in the clear, uncompromising style Herb Schildt is famous for
Head First Java: A Brain-Friendly Guide
- Engaging Learning: It uses a fun approach to teach Java and object-oriented programming.
- Comprehensive Content: Covers Java's basics and advanced topics like lambdas and GUIs.
- Interactive Learning: The book's visuals and engaging style make learning Java more enjoyable.
Modern Java in Action: Lambdas, streams, functional and reactive programming
- Latest Java Features: Explores modern Java functionalities from version 8 and beyond, like streams, modules, and concurrency.
- Real-world Applications: Demonstrates how to use these new features practically, enhancing understanding and coding skills.
- Developer-Friendly: Tailored for Java developers already familiar with core Java, making it accessible for advancing their expertise.
- Java Essentials: Learn fundamental Java programming through easy tutorials and practical tips in the latest edition of the For Dummies series.
- Programming Basics: Gain control over program flow, master classes, objects, and methods, and explore functional programming features.
- Updated Coverage: Covers Java 17, the latest long-term support release, including the new 'switch' statement syntax, making it perfect for beginners or those wanting to brush up their skills.
Add a Comment