Introduction to the Scanner Class for Input
The Scanner class in Java is the tool that performs this cutting.
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?
Reveal 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.
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.
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?
- 1First 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.
- 2Second 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.
- 3Third 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.
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.
| Method | What it reads | What it returns | Typical use |
|---|---|---|---|
| next() | The next token | A String, exactly as typed | Words, codes, or text values |
| nextInt() | The next token | An int, converted from the token | Whole-number values |
| nextDouble() | The next token | A double, converted from the token | Decimal values |
| nextLine() | Everything up to the end-of-line marker | A String that may contain spaces, or be empty | Reading a full line of text |
Choosing a read method based on what the program needs
12
apple
3.5nextInt()converts the token 12 into an intnext()returns the token apple as a String, unchangednextDouble()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.
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.
System.inselects 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.
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.
[]
Hello therenextInt()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?
Reveal 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.
3 scores, total 248
abchasNextInt()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 likenextInt() reads 42 from the input 42 newline Hello there, then nextLine() returns the empty string.
Why it failsnextInt()reads only the token. The end-of-line marker after the number is still waiting, andnextLine()consumes it and returns the text before it, which is empty.Do this insteadAfter 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 likeAssuming next() returns the text 12 followed by spaces when the input is 12 and two spaces then apple.
Why it failsDelimiters 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 insteadUse 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 failsA 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 insteadTest 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 likeCalling nextInt() when the next token is abc.
Why it failsnextInt()tries to convert the next token into an int. A token such as abc cannot be converted.Do this insteadUse 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
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
- 1A 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.
- 2next returns a token as a String,
nextIntandnextDoubleconvert the next token to a primitive type, andnextLinereturns everything up to the end-of-line marker. - 3
hasNext,hasNextInt,hasNextDouble, andhasNextLinecheck whether a suitable token or line is waiting before a read is attempted. - 4The 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,
nextIntandnextDoubleto convert tokens to numbers, andnextLineto read a whole line that is not organized around tokens. - Mixing
nextIntwithnextLineleaves the end-of-line marker in the input, so the nextnextLinecall can return the empty string. - Create a Scanner from
System.in, a Reader, or a String, and usehasNext-style checks before each read to avoid reading past the end of the input.