Java.Util.Nosuchelementexception - Scanner Reading User Input

java.util.NoSuchElementException - Scanner reading user input

This has really puzzled me for a while but this is what I found in the end.

When you call, sc.close() in first method, it not only closes your scanner but closes your System.in input stream as well. You can verify it by printing its status at very top of the second method as :

    System.out.println(System.in.available());

So, now when you re-instantiate, Scanner in second method, it doesn't find any open System.in stream and hence the exception.

I doubt if there is any way out to reopen System.in because:

public void close() throws IOException --> Closes this input stream and releases any system resources associated with this stream. The general contract of close is that it closes the input stream. A closed stream cannot perform input operations and **cannot be reopened.**

The only good solution for your problem is to initiate the Scanner in your main method, pass that as argument in your two methods, and close it again in your main method e.g.:

main method related code block:

Scanner scanner = new Scanner(System.in);  

// Ask users for quantities
PromptCustomerQty(customer, ProductList, scanner );

// Ask user for payment method
PromptCustomerPayment(customer, scanner );

//close the scanner
scanner.close();

Your Methods:

 public static void PromptCustomerQty(Customer customer, 
ArrayList<Product> ProductList, Scanner scanner) {

// no more scanner instantiation
...
// no more scanner close
}


public static void PromptCustomerPayment (Customer customer, Scanner sc) {

// no more scanner instantiation
...
// no more scanner close
}

Hope this gives you some insight about the failure and possible resolution.

Fixing java.util.NoSuchElementException for Scanner

Stop the madness of closing a Scanner linked to System.in! It will close the underlying stream (System.in), causing any other attempt to read from that Stream to throw an exception.

Yes you will get a warning, but it is safe to ignore that warning, or you can add

@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);

To avoid it.

Remember, if you didn't open a resource, you shouldn't close it. Let the JVM close it when it terminates the program.


This also includes creating a Scanner(System.in) inside a try with resources block:

try(Scanner in = new Scanner(System.in)){
//Code...
}

This will implicitly close the stream at the end of the block.

From the Java tutorials:

The try-with-resources statement ensures that each resource is closed at the end of the statement.


Also you have several Scanner objects reading from System.in, which is bad practice. I would pass them to your methods as a parameter:

public static double solvingForMass(Scanner in) {

System.out.println("Please enter a value for force.");
double f = in.nextDouble();

System.out.println("Please enter a value for acceleration.");
double a = in.nextDouble();

return f / a;

}

Also just a note that if you are ever doing the structure of:

if(someBool)
return true;
else
return false;

It can be simplified to just

return someBool

So your isValidChoice() method can be simplified to:

public static boolean isValidChoiceChar(String c) {
return c.compareTo("Y") == 0 || c.compareTo("N") == 0;
}

Although note you can use the equals() and equalsIgnoreCase()methods to compareString`'s

java.util.NoSuchElementException when reading user input in switch statement

In your addBookToLibrary method, you close the Scanners after you are done using them. However, those scanners are connected to System.in, the standard input stream. Closing those scanners will also close the standard input stream, according to the documentation.

What else is connected to the standard input stream? userMenuChoiceScanner! After the standard input stream is closed, userMenuChoiceScanner can't read from it, hence throwing an exception.

Note that although userMenuChoiceScanner is not closed until the very end, the stream that it is reading from is closed.

In fact, you don't need to create multiple scanners here. You only need to use one scanner, and pass it around to different methods. For example, addBookToLibrary could accept a Scanner:

public static void addBookToLibrary(Library library, Scanner s) {

And it will only use s to read inputs. You can pass your userMenuChoiceScanner to it:

addBookToLibrary(library, userMenuChoiceScanner);

As a general rule, you should not close anything that is not opened by you. You didn't open the standard input stream (the JVM did), so you shouldn't close it.

NoSuchElementException in java.util.Scanner

NoSuchElementException is thrown from Scanner.next() if you are trying to read data when you have reached the end of the data stream.

Instead of:

sc.next();
...

use:

while(! sc.hasNext()) { }
sc.next();
...

Scanner.hasNext() checks if there is any more data to read, and the while loop waits until there is more data to read before continuing.

JAVA - user input java.util.NoSuchElementException from scanner

If input is exhausted,it will throw java.util.NoSuchElementException on method 'nextInt'.
When a Scanner is closed, it will close its input source if the source implements the Closeable interface.So when you invoke'reader.close()',it also close system.in inputstream.

System.in is a static propertie.So after closing, it is not available.

public final class System {

/* register the natives via the static initializer.
*
* VM will invoke the initializeSystemClass method to complete
* the initialization for this class separated from clinit.
* Note that to use properties set by the VM, see the constraints
* described in the initializeSystemClass method.
*/
private static native void registerNatives();
static {
registerNatives();
}

/** Don't let anyone instantiate this class */
private System() {
}

/**
* The "standard" input stream. This stream is already
* open and ready to supply input data. Typically this stream
* corresponds to keyboard input or another input source specified by
* the host environment or user.
*/
public final static InputStream in = null;
...
}

NoSuchElementException with Java.Util.Scanner

NoSuchElementException Thrown by the nextElement method of an Enumeration to indicate that there are no more elements in the enumeration.

http://docs.oracle.com/javase/7/docs/api/java/util/NoSuchElementException.html

How about this :

if(input.hasNextInt() )
number1 = input.nextInt(); // if there is another number
else
number1 = 0; // nothing added in the input

Scanner next() throwing NoSuchElementException for some online compilers

This exception gets thrown because there are no more elements in the enumeration.

See the documentation:

Thrown by the nextElement method of an Enumeration to indicate that
there are no more elements in the enumeration.


Some online IDEs don't allow user input at all, in which case the exception will get thrown as soon as you try to read user input.

  1. It works on TutorialsPoint IDE because it allows user input.
  2. It doesn't works on codechef and compilejava IDEs because these IDEs does not support user input.

However there's secondary way to add user input on codechef. Just tick mark on Custom Input checkbox and provide any input. It will then compile.

Sample Image


Another reason for this exception, i.e. there simply not being more user input, can be handled by, before calling s.next(), just checking s.hasNext() to see whether the scanner has another token.

  Scanner s = new Scanner(System.in);
System.out.print("Enter name: ");
String name = null;
if(s.hasNext())
name = s.next();
System.out.println("Name is " + name);


Related Topics



Leave a reply



Submit