Concepts / Introduction to the Scanner Class for Input

Introduction to the Scanner Class for Input

The Scanner class in Java is the tool that performs this cutting.

  • Programming

A Stream of Characters Waiting to Be Cut

Imagine a program that asks a user to type several test scores on a single line, separated by spaces. The program does not receive a neat list of numbers. It receives one long stream of characters, and somewhere inside that stream are the individual scores the program actually cares about. Before the program can do anything useful, it needs a way to cut that stream into meaningful pieces.

The Scanner class in Java is the tool that performs this cutting. It was introduced in the package java.util to make reading basic data types from a character input source easier. Java's built-in support for basic input has long been considered thin, or dependent on fairly advanced techniques, so the Scanner was added for everyday use. It is not a complete solution to every input problem, but it is a substantial improvement for beginners and for many ordinary programs.

What do you think happens?

Before reading further: a program creates two Scanner objects, one from System.in and one from a String. What is each Scanner reading characters from?

  • Both read from the keyboard

  • One reads from standard input and the other reads from the text stored in the String

  • Both read from a file on disk

  • Neither reads anything until a print statement runs

Reveal answer
Answer:

One reads from standard input and the other reads from the text stored in the String

The constructor argument selects the source. Passing System.in means standard input, which is the keyboard in a typical console run. Passing a String means the Scanner reads that String from beginning to end.

Tokens and the Delimiters That Separate Them

A token is one meaningful piece of input. Tokens are separated from one another by delimiters. Unless you change the setting, a Scanner uses whitespace as its delimiter. Here, whitespace means spaces, tabs, and end-of-line markers. Those separator characters tell the scanner where one token stops and the next one begins.

Once the separation has done its job, the whitespace itself is set aside. It is not handed to your program as part of any token. Keep this in mind, because it explains a surprise you will meet later when reading whole lines.

12token 1two spacesdelimiter, not returnedappletoken 2newlinedelimiter, not returned3.5token 3
Given the input 12 followed by two spaces, then apple, a line break, and 3.5, the Scanner produces three tokens. The whitespace characters are used only to mark where each token ends.

Reading the diagram from left to right: the number 12 is one token, apple is another, and 3.5 is the third. The spaces and the line break sit between tokens and mark the boundaries, but they are not part of any token that the program receives.

Worked example

Reading three tokens with next

Given the input text 12, two spaces, apple, a line break, and 3.5, what does each call to next() return?

  1. 1
    First call to next()

    The Scanner skips past any leading delimiters and reads characters up to the next delimiter. It returns the text 12 as a String.

  2. 2
    Second call to next()

    The two spaces are delimiters, so they separate 12 from apple and are not returned. The Scanner reads apple and returns it as a String.

  3. 3
    Third call to next()

    The line break is a delimiter. The Scanner reads 3.5 and returns it as a String, still exactly as the characters appeared.

Result

The program receives the three Strings 12, apple, and 3.5. Each one is a single token, and no whitespace appears in any of them.

Choosing a Read Method for the Data

The most basic reading method is next. Each call to next reads the next token from the input source and returns it as a String. Because the return type is String, the program receives the token exactly as the characters appeared, with no attempt to interpret them as numbers. This makes next the right choice when the input is words, codes, or any value you want to keep as text.

Most of the time, a program reading numbers does not want the text version. Methods such as nextInt and nextDouble read the next token and then try to convert it into a value of type int or double. The same family of methods exists for the other primitive types. The conversion is the key difference from next: the method reads the token and attempts to turn it into the requested primitive type, rather than returning the characters unchanged.

Token-based methods ignore line boundaries when they pick out pieces of input. Sometimes that is not what you want. The nextLine method works differently. It reads everything up to the next end-of-line marker and returns the result as a String. The end-of-line marker is consumed during the read, but it is not included in the returned text. Because nextLine is not organized around tokens, the returned text can contain spaces, tabs, and other whitespace exactly as the user typed them. If the user presses Enter immediately, the returned value is the empty string.

MethodWhat it readsWhat it returnsTypical use
next()The next tokenA String, exactly as typedWords, codes, or text values
nextInt()The next tokenAn int, converted from the tokenWhole-number values
nextDouble()The next tokenA double, converted from the tokenDecimal values
nextLine()Everything up to the end-of-line markerA String that may contain spaces, or be emptyReading a full line of text

Choosing a read method based on what the program needs

java
Output
12
apple
3.5
Notes on the code
  • nextInt() converts the token 12 into an int
  • next() returns the token apple as a String, unchanged
  • nextDouble() converts the token 3.5 into a double

Creating a Scanner from Its Source

A Scanner is a wrapper around an input source. It does not own the characters it reads. The source is chosen by the constructor: whatever you pass into the parentheses when you write new Scanner is the place the Scanner will draw characters from. The input routines, such as next and nextInt, are instance methods defined on the class, so you must create a Scanner object before you can call them.

java

The word source in that pattern is a placeholder for one of the permitted kinds of input. The constructor accepts several kinds. The source text names four of them directly: a Reader, an InputStream, a String, and a File. It notes that other possibilities exist, so treat those four as the set the source explicitly names rather than a complete list.

The most common case in introductory programs is reading from standard input, which is the keyboard in a typical console run. Passing System.in to the constructor tells the Scanner to read from standard input.

java
Notes on the code
  • System.in selects standard input as the source
  • A String literal is read from beginning to end
  • A variable of type Reader is passed in the same way; the Scanner is wrapped around whatever you pass

The three Scanners above differ only in the argument. Each one is wrapped around a different source, and each one exposes the same reading methods. Once the object exists, next, nextInt, and nextLine work the same way regardless of where the characters came from.

Tracing Characters from Source to Program

Follow the path of characters. The source holds the raw characters. The Scanner is created around that source, and it divides those characters into tokens using delimiters. Each read method then takes the next piece from that division and hands it to the program, either as a String or converted to a primitive type.

Input sourceSystem.in, Reader, orStringScannersplits by delimitersTokens or linespieces of the streamProgram variablereturned by next, nextInt,nextLinecharacterscut aparteach read call
Characters travel from the source named in the constructor into the Scanner, which divides them into tokens or lines. Read method calls then pass each piece out to a program variable.

The same pipeline explains why the order of reads matters. The Scanner keeps its place in the source. Each read consumes what it needs and leaves the rest waiting for the next call. The next section shows exactly where that place sits after a token-based read.

Where nextInt Leaves the Input Position

nextInt reads the token 42 and converts it to an int. It stops at the end of that token. The end-of-line marker that follows 42 is a delimiter, and it has not been consumed by nextInt, because nextInt is organized around tokens and not lines. The marker is still waiting in the input.

42 newline Hellotherenothing read yetAfter nextInt()42 read, newline stillwaitingAfter firstnextLine()newline consumed, emptystring returnedAfter secondnextLine()Hello there returnednextInt()nextLine()nextLine()
After nextInt() reads 42, the end-of-line marker is still waiting. The following nextLine() consumes that marker and returns the empty text before it, so the second read returns an empty string.
java
Output
[]
Hello there
Notes on the code
  • nextInt() returns 42 and leaves the line break in the input
  • The first nextLine() consumes the line break and returns the empty string
  • The second nextLine() returns the text Hello there

What do you think happens?

Given new Scanner("42\nHello there"), the program calls nextInt() and then nextLine(). What does the nextLine() call return?

  • Hello there

  • An empty string

  • 42

  • The program stops with an error

Reveal answer
Answer:

An empty string

nextInt() reads only the token 42. The end-of-line marker after it is still in the input, so nextLine() reads up to that marker and returns the empty string. Calling nextLine() a second time returns Hello there.

Checking Before Reading with hasNext

A program often needs to know whether there is anything left to read before it attempts a read. The hasNext method answers that question for tokens. It returns a boolean value that is true when at least one more token remains in the input source. The companion methods hasNextInt and hasNextDouble go a step further. They return true only when the next token exists and represents a value of the requested type. The hasNextLine method plays the same role for lines, returning true when at least one more line remains.

The pattern most programs follow is that a check comes first, and a read happens only when the check says a value is waiting. This keeps a loop from trying to read past the end of its input. The typed check matters as well. A hasNextInt test confirms not only that a token exists but that the token can be read as an int, so the check and the read agree with each other.

java
Output
3 scores, total 248
abc
Notes on the code
  • hasNextInt() is true for 70, 85, and 93, so each is read as an int
  • The loop stops at abc because the next token is not an int
  • The token abc is still waiting and can be read with next()

Mixing Token and Line Reading

Most of the trouble beginners meet with Scanner comes from switching between token-based and line-based reading without thinking about where the input position sits. The following mistakes come up repeatedly.

  • Common mistake

    Calling nextLine() immediately after nextInt() and expecting the next line of text

    What it looks like

    nextInt() reads 42 from the input 42 newline Hello there, then nextLine() returns the empty string.

    Why it fails

    nextInt() reads only the token. The end-of-line marker after the number is still waiting, and nextLine() consumes it and returns the text before it, which is empty.

    Do this instead

    After a token read, call nextLine() once to discard the leftover line, then call nextLine() again to read the line you want.

  • Common mistake

    Expecting the whitespace between tokens to appear inside the tokens

    What it looks like

    Assuming next() returns the text 12 followed by spaces when the input is 12 and two spaces then apple.

    Why it fails

    Delimiters separate tokens. Once the separation is done, the whitespace is set aside and is not handed to the program as part of any token.

    Do this instead

    Use next() or nextInt() for individual tokens. Use nextLine() when the spaces inside a line are themselves part of the data.

  • Common mistake

    Reading in a loop without checking whether input remains

    Why it fails

    A read with no input left has nothing to return, so an unchecked loop can try to read past the end of its input.

    Do this instead

    Test with hasNext, hasNextInt, or hasNextLine before each read so that the check and the read agree.

  • Common mistake

    Using nextInt() when the next token is not a whole number

    What it looks like

    Calling nextInt() when the next token is abc.

    Why it fails

    nextInt() tries to convert the next token into an int. A token such as abc cannot be converted.

    Do this instead

    Use hasNextInt() first to confirm the token has the requested type, or use next() to read it as text.

  • Common mistake

    Forgetting to create a Scanner object before calling input methods, since they are instance methods

Practice Reading Mixed Input

MEDIUM

A Scanner is created from the String "5 7\nsun rise". Write the statements that read the two integers 5 and 7 with nextInt, then read the remaining line with nextLine so that it contains sun rise. Say what the first nextLine() call returns and why.

Hints
  • Two nextInt() calls read 5 and 7, but the line break after 7 is still waiting.
  • The first nextLine() after the integers returns the text between the current position and the line break, which is empty.
  • A second nextLine() reads sun rise.

Summary of Scanner Input

  1. 1
    A Scanner splits input into tokens. By default the delimiters are whitespace: spaces, tabs, and end-of-line markers, and that whitespace is not returned as part of any token.
  2. 2
    next returns a token as a String, nextInt and nextDouble convert the next token to a primitive type, and nextLine returns everything up to the end-of-line marker.
  3. 3
    hasNext, hasNextInt, hasNextDouble, and hasNextLine check whether a suitable token or line is waiting before a read is attempted.
  4. 4
    The constructor argument selects the source, such as System.in, a Reader, or a String, and input methods are called on the Scanner object you create.

At a glance

  • A Scanner splits input into tokens, and by default the separators are whitespace characters such as spaces, tabs, and end-of-line markers.
  • Use next for text tokens, nextInt and nextDouble to convert tokens to numbers, and nextLine to read a whole line that is not organized around tokens.
  • Mixing nextInt with nextLine leaves the end-of-line marker in the input, so the next nextLine call can return the empty string.
  • Create a Scanner from System.in, a Reader, or a String, and use hasNext-style checks before each read to avoid reading past the end of the input.

Related concepts

More concepts starting with I