CMPS 134: Introduction to Java's Scanner Class

An instance of the java.util.Scanner class is for reading from a source of textual input data. The most likely source of such data is the keyboard (System.in) or a text file (typically having a .txt extension). A Scanner can also be set up to read from a value of type String. Any class that uses a Scanner must include the appropriate import statement above the class heading:

import java.util.Scanner;

When creating an instance of the Scanner class (i.e., a Scanner object), you must use the new operator and specify the source from which it is to read data. Examples:

ExpressionEffect
new Scanner(System.in) Creates a Scanner that can read from the keyboard
new Scanner(new File("glorp.txt")) Creates a Scanner that can read from the file named glorp.txt
new Scanner("Chris Smith 4 8.2 7.6 8.5 9.0") Creates a Scanner that can "read" from the specified String

Typically, an expression such as shown in the table above will occur as the right-hand side of an assignment statement (possibly combined with a declaration), as in the familiar

Scanner keyboard = new Scanner(System.in);

Ann Gourdhead     1989-11-30 23.40 
Jim 2000     17  engineer
    2.7E-5 -15
A Scanner object interprets input data as a sequence of tokens that are separated by whitespace characters. (Whitespace characters include spaces, tabs, and newline characters.) For example, suppose that the figure to the right shows the contents of a file of text. A Scanner would interpret this file as containing ten tokens: "Ann", "Gourdhead", "1989-11-30", "23.40", "Jim", "2000", "17", "engineer", "2.7E-5", and "-15".

You can think of a Scanner as having a cursor that keeps track of its position within the text. When first created, a Scanner's cursor is positioned, as you would expect, at the beginning of the input text. A Scanner has several functional methods —each with a name having next as a prefix— that return the "next" token and cause the cursor to advance just beyond that token. Which of these methods you would call (to read the next token) depends upon what type of value you expect the next token to represent: int, double, boolean, String, etc.


Letting input be of type Scanner, here are examples of invocations of methods in the java.util.Scanner class:

method
Invocation
Return Type Value Returned Side Effect Possible Exceptions
input.next() String the next input token the cursor has advanced past the returned token java.util.NoSuchElementException
input.hasNext() boolean true if there is a next input token, false otherwise none none
input.nextInt() int the next input token, translated into a value of type int. Throws InputMismatchException if the next token is not of a form that can be translated into an integer. the cursor has advanced past the returned token java.util.NoSuchElementException
java.util.InputMismatchException
input.hasNextInt() boolean true if there is a next input token and it is of a form that can be translated into an integer, false otherwise none none
input.nextDouble() int the next input token, translated into a value of type double. Throws InputMismatchException if the next token is not of a form that can be translated into a real number. the cursor has advanced past the returned token java.util.NoSuchElementException
java.util.InputMismatchException
input.hasNextDouble() boolean true if there is a next input token and it is of a form that can be translated into a real number, false otherwise none none
input.nextLine() String the rest of the current line of input (up to a newline character) the cursor has advanced to the beginning of the next line java.util.NoSuchElementException
input.hasNextLine() boolean true if there is more input data (even if it is all whitespace and therefore no tokens remain) none none

Any token can be read as a String using next().

The methods that read in the "next token" (e.g., next(), nextInt(), etc.) do not respect line boundaries. That is, they treat an occurrence of the newline character just as though it were a space. Thus, a call to any of these methods will move the cursor forward, past the next token (which it will return), even if that token appears one or more lines below the cursor's position.

Ann Gourdhead     1989-11-30 23.40 
Jim 2000     17  engineer
    2.7E-5 -15
For a token to be readable via the nextInt() method, it must be a sequence of characters that could serve as an int literal in a Java program. Among the tokens in the example to the right, only "2000", "17", and "-15" meet this condition. Attempting to read any other token using nextInt() would result in an InputMismatchException being thrown.

For a token to be readable via the nextDouble() method, it must be a sequence of characters that could serve as a double literal in a Java program. Among the tokens in this example, that includes all the ones that could serve as int literals, plus 23.40 and 2.7E-5. Attempting to read any other token using nextDouble() would result in an InputMismatchException being thrown.

If the cursor is positioned after the very last token in a source of input, an attempt to read the next token using any of nextXXX() methods results in a NoSuchElementException being thrown. Similarly, if the cursor has advanced beyond the end of the last line of input, calling nextLine() results in a NoSuchElementException being thrown.

The nextLine() method is a bit unique in that it doesn't read a token but rather all the characters up to the end of the current line (i.e., up to the next occurrence of a newline character), which may include zero or more tokens. The cursor advances to the beginning of the next line.

This behavior is a frequent source of confusion, because it seems natural to assume that if the last token on a line already has been read (e.g., using one of the nextXXX() methods that reads a single token), the cursor would have advanced to the beginning of the next line. But that is not how it works.

Elmo Wright
Kansas City Chiefs
To illustrate, suppose that a program was using a Scanner to read the data in a file describing former NFL players. Each player is represented on two lines, the first of which contains his first and last names and the second of which contains the name of a team on which he played. Imagine that the Scanner's cursor was at the beginning of the data shown to the right (so the next token was "Elmo").

You might think that execution of the code segment shown below and left would have the desired effect (where in refers to the Scanner):

String firstName = in.next();
String lastName = in.next();
String team = in.nextLine();
String firstName = in.next();
String lastName = in.next();
in.nextLine();  // advance to line containing team name
String team = in.nextLine();
WRONG!RIGHT!

But you would be wrong, because the second call to next() leaves the cursor at the position immediately following the 't' in "Wright", and not at the beginning of the next line. The call to nextLine(), therefore, will advance the token to the beginning of the second line, passing over the (zero or more) spaces and the newline character that follows that 't'. The String returned by that call will be the string composed of those (zero or more) spaces.

To get the desired effect, it is necessary to call nextLine() twice, the first time to advance the cursor to the second line and the second time to read the data on that line (i.e., the team name).