In this post, I’ll share the top best answers to the above-mentioned problem.
Problem:
I am using the Scanner
methods nextInt()
and nextLine()
for reading input.
It looks like this:
System.out.println("Enter numerical value");
int option;
option = input.nextInt(); // Read numerical value from input
System.out.println("Enter 1st string");
String string1 = input.nextLine(); // Read 1st string (this is skipped)
System.out.println("Enter 2nd string");
String string2 = input.nextLine(); // Read 2nd string (this appears right after reading numerical value)
The problem is that after entering the numerical value, the first input.nextLine()
is skipped and the second input.nextLine()
is executed, so that my output looks like this:
Enter numerical value
3 // This is my input
Enter 1st string // The program is supposed to stop here and wait for my input, but is skipped
Enter 2nd string // ...and this line is executed and waits for my input
I tested my application and it looks like the problem lies in using input.nextInt()
. If I delete it, then both string1 = input.nextLine()
and string2 = input.nextLine()
are executed as I want them to be.
Answer #1:
That’s because the Scanner.nextInt
method does not read the newline character in your input created by hitting “Enter,” and so the call to Scanner.nextLine
returns after reading that newline.
You will encounter the similar behaviour when you use Scanner.nextLine
after Scanner.next()
or any Scanner.nextFoo
method (except nextLine
itself).
Workaround:
- Either put a
Scanner.nextLine
call after eachScanner.nextInt
orScanner.nextFoo
to consume rest of that line including newlineint option = input.nextInt(); input.nextLine(); // Consume newline left-over String str1 = input.nextLine();
- Or, even better, read the input through
Scanner.nextLine
and convert your input to the proper format you need. For example, you may convert to an integer usingInteger.parseInt(String)
method.int option = 0; try { option = Integer.parseInt(input.nextLine()); } catch (NumberFormatException e) { e.printStackTrace(); } String str1 = input.nextLine();
Answer #2:
The problem is with the input.nextInt() method – it only reads the int value. So when you continue reading with input.nextLine() you receive the “\n” Enter key. So to skip this you have to add the input.nextLine(). Hope this should be clear now.
Try it like that:
System.out.print("Insert a number: ");
int number = input.nextInt();
input.nextLine(); // This line you have to add (It consumes the \n character)
System.out.print("Text1: ");
String text1 = input.nextLine();
System.out.print("Text2: ");
String text2 = input.nextLine();
Answer #3:
Use scanner.skip("\\R")
(since skip
uses regex where \R
represents line separators) before each scanner.newLine()
call, which is executed after:
scanner.next()
scanner.next*TYPE*()
method, likescanner.nextInt()
.
OR safer variant: scanner.skip("\\R?")
before each scanner.nextLine()
if you are not sure if it will be called after scanner.next()
or scanner.next*TypeName*()
. ?
will make line separator sequence optional (this will prevent skip
method from (a) waiting for matching sequence – in case of still opened source of data like System.in
(b) throwing java.util.NoSuchElementException
in case of terminated/ended source of data like File or String)
Things you need to know:
- text which represents few lines also contains non-printable characters between lines (we call them line separators) like
- carriage return (CR – in String literals represented as
"\r"
) - line feed (LF – in String literals represented as
"\n"
) - when you are reading data from the console, it allows the user to type his response and when he is done he needs to somehow confirm that fact. To do so, the user is required to press “enter”/”return” key on the keyboard.
What is important is that this key beside ensuring placing user data to standard input (represented by System.in
which is read by Scanner
) also sends OS dependant line separators (like for Windows \r\n
) after it.
So when you are asking the user for value like age
, and user types 42 and presses enter, standard input will contain "42\r\n"
.
Problem
Scanner#nextInt
(and other Scanner#nextType
methods) doesn’t allow Scanner to consume these line separators. It will read them from System.in
(how else Scanner would know that there are no more digits from the user which represent age
value than facing whitespace?) which will remove them from standard input, but it will also cache those line separators internally. What we need to remember, is that all of the Scanner methods are always scanning starting from the cached text.
Now Scanner#nextLine()
simply collects and returns all characters until it finds line separators (or end of stream). But since line separators after reading the number from the console are found immediately in Scanner’s cache, it returns empty String, meaning that Scanner was not able to find any character before those line separators (or end of stream).
BTW nextLine
also consumes those line separators.
Solution
So when you want to ask for number and then for entire line while avoiding that empty string as result of nextLine
, either
- consume line separator left by
nextInt
from Scanners cache by - calling
nextLine
, - or IMO more readable way would be by calling
skip("\\R")
orskip("\r\n|\r|\n")
to let Scanner skip part matched by line separator, - don’t use
nextInt
(nornext
, or anynextTYPE
methods) at all. Instead read entire data line-by-line usingnextLine
and parse numbers from each line (assuming one line contains only one number) to proper type likeint
viaInteger.parseInt
.
BTW: Scanner#nextType
methods can skip delimiters (by default all whitespaces like tabs, line separators) including those cached by scanner, until they will find next non-delimiter value (token). Thanks to that for input like "42\r\n\r\n321\r\n\r\n\r\nfoobar"
code
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String name = sc.next();
will be able to properly assign num1=42
num2=321
name=foobar
.
Answer #4:
Instead of input.nextLine()
use input.next()
, that should solve the problem.
Modified code:
public static Scanner input = new Scanner(System.in);
public static void main(String[] args)
{
System.out.print("Insert a number: ");
int number = input.nextInt();
System.out.print("Text1: ");
String text1 = input.next();
System.out.print("Text2: ");
String text2 = input.next();
}
Answer #5:
Use 2 scanner objects instead of one
Scanner input = new Scanner(System.in);
System.out.println("Enter numerical value");
int option;
Scanner input2 = new Scanner(System.in);
option = input2.nextInt();
I hope your query has been resolved.
Follow Programming Articles for more!