Pétur Ingi Egilsson
Pétur Ingi Egilsson

Reputation: 4493

Use of Scanners nextLine() throws NoSuchElementException

Im getting NoSuchElementException when running nextLine() two times on the same console while using println in between their runs.

First I run this:

  public void ask() {
    System.out.print(title);
    answer = getAnswer();
  }
  private String getAnswer() {
    System.out.println("Before first nextLine()");
    final Scanner in = new Scanner(System.in);
    final String input = in.nextLine();
    in.close();
    System.out.println("After first nextLine()");
    return input;
  }

Then I run this:

  @Override
  public void ask() {
    System.out.println(title);
    int index = 0;
    for (Option o : options)
      System.out.println(index++ + " : " + o.getTitle());
    System.out.println("Before second nextLine()");
    final Scanner in = new Scanner(System.in);
    String answer = in.nextLine();
    in.close();
    System.out.println("After second nextLine()");

    this.answer = options.get(Integer.parseInt(answer)).getTitle();
  }

Here is the output:

 How old are you?Before first nextLine()
32
Exception in thread "main" java.util.NoSuchElementException: No line found
After first nextLine()
    at java.util.Scanner.nextLine(Scanner.java:1540)
Sex
    at SingleChoise.ask(SingleChoise.java:25)
0 : Male
    at Main.main(Main.java:17)
1 : Female
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Before second nextLine()
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)

Why is the exception thrown and how to I fix this?

Upvotes: 3

Views: 1134

Answers (3)

Alex Fitzpatrick
Alex Fitzpatrick

Reputation: 644

From the javadoc:

 * When searching, if no line terminator is found, then a large amount of
 * input will be cached. If no line at all can be found, a
 * NoSuchElementException will be thrown out.

Upvotes: 0

Minty Fresh
Minty Fresh

Reputation: 683

One thing about the Scanner class is that calling Scanner.close() on the Scanner will also close the input stream it's reading from. In this case, that's closing System.in, which cannot be reopened once it has been closed.

If possible, you should declare your Scanner at class level, and leave it open. Classes reading from System.in generally need not be closed.

Upvotes: 3

mk.
mk.

Reputation: 11730

You are closing the underlying stream, System.in, when you write:

final Scanner in = new Scanner(System.in);
final String input = in.nextLine();
in.close();

You don't need to do that. Remove the close call. You might also consider using the same Scanner throughout (perhaps pass it around, or put it in a static field).

Upvotes: 3

Related Questions