2

Here's a reduced version of the code that's throwing the exception.

static String s1;
static String s2;

static void getString(String s) {
    Scanner sc = new Scanner(System.in);
    s = sc.nextLine();
    sc.close();
}

public static void main(String[] args) {
    getString(s1);
    getString(s2);
}

Exception in thread "main" java.util.NoSuchElementException: No line found at java.util.Scanner.nextLine(Scanner.java:1540) at temp.Temp.getString(Temp.java:13)

I'm calling the getString method twice, and on second call it breaks on:

s = sc.nextLine();

Now, I understand that removing the sc.close() line solves the problem (and making sc a static variable probably, too). What I need to grasp is WHY this is the case.

I read the specification of the scanner class but couldn't deduce. I also read several posts on this exception including this one, which says that closing the scanner also closes the underlying stream. But I'm creating a new scanner and reopening the stream with every method call, no?

Mureinik
  • 297,002
  • 52
  • 306
  • 350
John Allison
  • 966
  • 1
  • 10
  • 30
  • 2
    You're not creating a new stream. You're always using the same stream: System.in. When it's closed, it's closed. – JB Nizet Dec 06 '18 at 07:01
  • @JBNizet, yes, noted it, just corrected this to 'reopening'. The question still persists, though. Or you mean that, once closed, it can't be reopened no matter what? – John Allison Dec 06 '18 at 07:01
  • 1
    When you close the scanner it closes the stream it is using, that is System.in – Joakim Danielson Dec 06 '18 at 07:02
  • 1
    No, you're not "reopening" anything. A stream cannot be reopened, and there is no "reopening" anywhere. You're using a single stream, and when it's closed, it's closed. Forever. – JB Nizet Dec 06 '18 at 07:03

2 Answers2

3

There is no such thing as "reopening a stream". The only thing you can do is create a new stream, with a new Scanner, and optionally place it in the same variable.

Once you close sc, you also close the underlying System.in stream. Creating a new Scanner on top of it can't "reopen" it, and since the stream is closed, you get this exception.

To make a long story short - while it's definitely a good practice to close resources when you're done with them, you shouldn't close System.in (or any scanner based on it).

Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

You can not "re-open" System.in, System.out or System.err as explained here

As another solution to this you can use CloseShieldInputStream which is explained here

LenosV
  • 172
  • 1
  • 6