# Scanner
# General Pattern that does most commonly asked about tasks
The following is how to properly use the java.util.Scanner
class to interactively read user input from System.in
correctly( sometimes referred to as stdin
, especially in C, C++ and other languages as well as in Unix and Linux). It idiomatically demonstrates the most common things that are requested to be done.
package com.stackoverflow.scanner;
import javax.annotation.Nonnull;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import java.util.regex.Pattern;
import static java.lang.String.format;
public class ScannerExample
{
private static final Set<String> EXIT_COMMANDS;
private static final Set<String> HELP_COMMANDS;
private static final Pattern DATE_PATTERN;
private static final String HELP_MESSAGE;
static
{
final SortedSet<String> ecmds = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
ecmds.addAll(Arrays.asList("exit", "done", "quit", "end", "fino"));
EXIT_COMMANDS = Collections.unmodifiableSortedSet(ecmds);
final SortedSet<String> hcmds = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
hcmds.addAll(Arrays.asList("help", "helpi", "?"));
HELP_COMMANDS = Collections.unmodifiableSet(hcmds);
DATE_PATTERN = Pattern.compile("\\d{4}([-\\/])\\d{2}\\1\\d{2}"); // http://regex101.com/r/xB8dR3/1
HELP_MESSAGE = format("Please enter some data or enter one of the following commands to exit %s", EXIT_COMMANDS);
}
/**
* Using exceptions to control execution flow is always bad.
* That is why this is encapsulated in a method, this is done this
* way specifically so as not to introduce any external libraries
* so that this is a completely self contained example.
* @param s possible url
* @return true if s represents a valid url, false otherwise
*/
private static boolean isValidURL(@Nonnull final String s)
{
try { new URL(s); return true; }
catch (final MalformedURLException e) { return false; }
}
private static void output(@Nonnull final String format, @Nonnull final Object... args)
{
System.out.println(format(format, args));
}
public static void main(final String[] args)
{
final Scanner sis = new Scanner(System.in);
output(HELP_MESSAGE);
while (sis.hasNext())
{
if (sis.hasNextInt())
{
final int next = sis.nextInt();
output("You entered an Integer = %d", next);
}
else if (sis.hasNextLong())
{
final long next = sis.nextLong();
output("You entered a Long = %d", next);
}
else if (sis.hasNextDouble())
{
final double next = sis.nextDouble();
output("You entered a Double = %f", next);
}
else if (sis.hasNext("\\d+"))
{
final BigInteger next = sis.nextBigInteger();
output("You entered a BigInteger = %s", next);
}
else if (sis.hasNextBoolean())
{
final boolean next = sis.nextBoolean();
output("You entered a Boolean representation = %s", next);
}
else if (sis.hasNext(DATE_PATTERN))
{
final String next = sis.next(DATE_PATTERN);
output("You entered a Date representation = %s", next);
}
else // unclassified
{
final String next = sis.next();
if (isValidURL(next))
{
output("You entered a valid URL = %s", next);
}
else
{
if (EXIT_COMMANDS.contains(next))
{
output("Exit command %s issued, exiting!", next);
break;
}
else if (HELP_COMMANDS.contains(next)) { output(HELP_MESSAGE); }
else { output("You entered an unclassified String = %s", next); }
}
}
}
/*
This will close the underlying Readable, in this case System.in, and free those resources.
You will not be to read from System.in anymore after this you call .close().
If you wanted to use System.in for something else, then don't close the Scanner.
*/
sis.close();
System.exit(0);
}
}
# Using custom delimiters
You can use custom delimiters (regular expressions) with Scanner, with .useDelimiter(",")
, to determine how the input is read. This works similarly to String.split(...)
. For example, you can use Scanner
to read from a list of comma separated values in a String:
Scanner scanner = null;
try{
scanner = new Scanner("i,like,unicorns").useDelimiter(",");;
while(scanner.hasNext()){
System.out.println(scanner.next());
}
}catch(Exception e){
e.printStackTrace();
}finally{
if (scanner != null)
scanner.close();
}
This will allow you to read every element in the input individually. Note that you should not use this to parse CSV data, instead, use a proper CSV parser library, see CSV parser for Java (opens new window) for other possibilities.
# Reading system input using Scanner
Scanner scanner = new Scanner(System.in); //Scanner obj to read System input
String inputTaken = new String();
while (true) {
String input = scanner.nextLine(); // reading one line of input
if (input.matches("\\s+")) // if it matches spaces/tabs, stop reading
break;
inputTaken += input + " ";
}
System.out.println(inputTaken);
The scanner object is initialized to read input from keyboard. So for the below input from keyboar, it'll produce the output as Reading from keyboard
Reading
from
keyboard
//space
# Reading file input using Scanner
Scanner scanner = null;
try {
scanner = new Scanner(new File("Names.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (Exception e) {
System.err.println("Exception occurred!");
} finally {
if (scanner != null)
scanner.close();
}
Here a Scanner
object is created by passing a File
object containing the name of a text file as input. This text file will be opened by the File object and read in by the scanner object in the following lines. scanner.hasNext()
will check to see if there is a next line of data in the text file. Combining that with a while
loop will allow you to iterate through every line of data in the Names.txt
file. To retrieve the data itself, we can use methods such as nextLine()
,nextInt()
,nextBoolean()
, etc. In the example above, scanner.nextLine()
is used. nextLine()
refers to the following line in a text file, and combining it with a scanner
object allows you to print the contents of the line. To close a scanner object, you would use .close()
.
Using try with resources (from Java 7 onwards), the above mentioned code can be written elegantly as below.
try (Scanner scanner = new Scanner(new File("Names.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (Exception e) {
System.err.println("Exception occurred!");
}
# Read the entire input as a String using Scanner
You can use Scanner
to read all of the text in the input as a String, by using \Z
(entire input) as the delimiter. For example, this can be used to read all text in a text file in one line:
String content = new Scanner(new File("filename")).useDelimiter("\\Z").next();
System.out.println(content);
Remember that you'll have to close the Scanner, as well as catch the IoException
this may throw, as described in the example Reading file input using Scanner (opens new window).
# Read an int from the command line
import java.util.Scanner;
Scanner s = new Scanner(System.in);
int number = s.nextInt();
If you want to read an int from the command line, just use this snippet. First of all, you have to create a Scanner object, that listens to System.in, which is by default the Command Line, when you start the program from the command line. After that, with the help of the Scanner object, you read the first int that the user passes into the command line and store it in the variable number. Now you can do whatever you want with that stored int.
# Carefully Closing a Scanner
it can happen that you use a scanner with the System.in as parameter for the constructor, then you need to be aware that closing the scanner will close the InputStream too giving as next that every try to read the input on that (Or any other scanner object) will throw an java.util.NoSuchElementException
or an java.lang.IllegalStateException
example:
Scanner sc1 = new Scanner(System.in);
Scanner sc2 = new Scanner(System.in);
int x1 = sc1.nextInt();
sc1.close();
// java.util.NoSuchElementException
int x2 = sc2.nextInt();
// java.lang.IllegalStateException
x2 = sc1.nextInt();
# Syntax
- Scanner scanner = new Scanner(Source source);
- Scanner scanner = new Scanner(System.in);
# Parameters
Parameter | Details |
---|---|
Source | Source could be either one of String, File or any kind of InputStream |
# Remarks
The Scanner
class was introduced in Java 5. The reset()
method was added in Java 6, and a couple of new constructors were added in Java 7 for interoperability with the (then) new Path
interface.
← File I/O Interfaces →