reset password
Author Message
rabbott
Posts: 1649
Posted 22:44 Nov 05, 2013 |

Bruno Recillas noticed a strange phenomenon.  I had written code similar to the following. (Basically, the class OrderedString has a constructor that creates a Scanner, reads a String from System.in, stores the String locally, and then closes the Scanner.)

    public static void main(String[] args) {
        OrderedString string1= new OrderedString("First string: ");
        OrderedString string2= new OrderedString("Second String: ");
        ...   // More stuff that doesn't matter for this problem.
    }

    public OrderedString(String prompt) {
        System.out.print(prompt);
        Scanner scanner = new Scanner(System.in);
        this.myString = scanner.next();
        scanner.close();
    }

This code works fine in BlueJ, but when executed from eclipse it throws a NoSuchElementException when reading the second string. (It reads the first one fine.)

Apparently the problem is with scanner.close(). Closing a scanner, closes its input source, which in this case is System.in. When we create a second Scanner and try to read from System.in a second time, an exception is thrown because System.in is closed.

This seems to be a common problem. Try to Google Java Scanner noSuchElementException.  (Not all the answers are useful. It's not necessary, for example, to try scanner.hasNext() before scanner.next().)

This seems to me like strange behavior. If calling scanner.close() closes the input source, it would make sense that creating a Scanner would open the input source. But apparently that doesn't happen--although perhaps it does when one creates a new Scanner(System.in) in BlueJ.

The bottom line is that when reading from System.in, it's best to use a single Scanner and not close it until all input has been read.

 

 

Last edited by rabbott at 09:04 Nov 06, 2013.