Bookmark Topic Watch Topic
  • Mark post as helpful
  • send pies
  • Report post to moderator
The java.util.Scanner can be quite useful in reading and parsing text from a file or the standard input stream, System.in, which typically corresponds to keyboard input or some other source directed to standard input by the host environment or user.

There is a fairly common pitfall you should be aware of when calling nextLine() on a Scanner that is taking input from the keyboard via System.in.

Gotcha! - nextLine() doesn't seem to stop and wait for the user to type something.

Consider this code, adapted from a question posted in Beginning Java:

After entering a number greater than or equal to 18, you might expect the program to stop and wait for you to type in an answer to the question "Have you ever voted before?" However, the code will appear to ignore the call to nextLine() on line 8 and go right away to line 11 and print "Goodbye!"

Please enter your age
18
Have you ever voted before?
Goodbye!

The reason you'll see this behavior is because when you type in a number and then hit ENTER (↵), a newline character is added to the input stream after the number. The nextInt() method will not consume that newline character; it only takes whatever characters it can take from the input stream that can be interpreted as part of an integer. When it gets to the newline, the Scanner will stop taking characters from the input stream and return the integer value that it read in. The subsequent call to nextLine() on line 8 will consume the newline character. Because it only consumes one line at a time, the newLine() method thinks that it's done once it reads in the newline from the input stream, so it doesn't stop to wait for the user to enter more characters.

If you type a space and some more characters after the number and then hit ENTER, whatever you typed after the number would actually be read by nextLine() and the answer variable would be assigned a string with all those characters, including the space but excluding the newline.

If we added a line to the above program so that it does this:

it would look something like this when you ran the program:

Please enter your age
18 yrs old
Have you ever voted before?
[ yrs old]
Goodbye!

The only time the program would stop and wait for you to type something would be after it prompts you to enter your age. When you hit ENTER right after typing the 'd' in the word "old," the program will display the text "Have you ever voted before?" and the nextLine() method will read in all the characters you typed in after the number 18. When it gets to the newline character representing ENTER, nextLine() will exit and return the String " yrs old" (including the leading space but excluding the newline), which then gets assigned to the answer variable which in turn is printed out on line 4.

One thing to note: this is only an issue when you call nextLine() immediately after calling any other nextXXX() method of Scanner besides nextLine().

There are a couple of workarounds to this little quirk of Scanner.

Workaround #1 - add an extra call to nextLine()

By adding an extra call to nextLine(), you will essentially take everything after the number that you entered, including the newline, out of the input stream. Since you're probably not interested in any of those characters anyway, you can just ignore the value returned by nextLine(). The next call to nextLine() will then work, and the program will stop and wait for you to type in something and hit ENTER again.

The workaround would look like this:

Workaround #2 - use next() instead of nextLine()

Instead of adding an extra call to nextLine(), you can just change the existing call from nextLine() to next() instead.

This works only if you expect the user to enter just one word in response to the prompt. This is because the next() method will only parse one token from the input stream. The nice thing about using next() in this case is that the user can actually hit ENTER as many times as he wants (or maybe accidentally) but as long as no valid characters that make up a token are read in by the Scanner, it will continue to wait for the user to enter something that is a valid token.

However, if you want the program to take all the characters the user types in before hitting ENTER, that is, you want the user to be able to type in multiple words for their response, you'd have to use Workaround #1.

Workaround #3 - use both next() and nextLine()

As Lisa Austin suggests here, calling next() moves the cursor to the end of the first token not containing whitespace, and nextLine() gives us the remainder of the same line. Simply concatenating them will give you the next line:-The thread mentioned in that link has lots more discussion in, including a loop which will find the next line containing printing characters (=non‑whitespace).
 
Consider Paul's rocket mass heater.
    Bookmark Topic Watch Topic
  • New Topic
Boost this thread!