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.
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.
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
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 compare
String`'s
Java scanner class no such element exception error
s.close();
closes the current Scanner
object, but also all underlying streams, which is System.in
in this case. Once your standard input stream is closed, you cannot open it anymore.
So all in all it would be best to close your Scanner after you're sure you won't need it anymore and restructure your code like this:
Scanner sc = new Scanner(System.in);
for (int i = 0; i < 10; i++) {
Student s = Test.readStudent(sc);
// do something with your student object here
}
sc.close();
And change your method to
public static Student readStudent(Scanner s) throws IOException {
Scanner s = new Scanner(System.in);
System.out.println("Enter first name of student");
String fname = s.nextLine();
System.out.println("Enter middle name of student");
String mname = s.nextLine();
System.out.println("Enter last name of student");
String lname = s.nextLine();
System.out.println("Enter name format(1 for ',' and 2 for ';') ");
int num = s.nextInt();
s.nextLine(); // Need to consume new line
System.out.println("Enter age of student");
int age = s.nextInt();
s.nextLine(); // Need to consume new line
// no closing here
return new Student(new Name(String.join((num == 1) ? "," : ";", fname,
mname, lname)), age);
}
java.util.NoSuchElementExeption regarding the Scanner class?
@Mert is sort of right, Scanner will close the underlying stream if it is Closable, and since you are using System.in when you instantiate another Scanner you are effectively passing a closed stream and thus the NotSuchElementException. Note the Scanner documentation for nextInt():
@throws NoSuchElementException if input is exhausted.
And for close():
If this scanner has not yet been closed then if its underlying readable also implements the Closeable interface then the readable's close method will be invoked.
So just close your Scanner at the end of your application.
Related Topics
Java.Sql.Sqlexception: - Ora-01000: Maximum Open Cursors Exceeded
Using Regular Expressions to Extract a Value in Java
Most Simple Code to Populate Jtable from Resultset
How to Randomly Pick an Element from an Array
How to Properly Override Clone Method
What Is the "Execute Around" Idiom
Why Jsf Saves the State of UI Components on Server
Nosuchmethoderror in Javax.Persistence.Table.Indexes()[Ljavax/Persistence/Index
How to Switch to the New Browser Window, Which Opens After Click on the Button
Closing Database Connections in Java
Java Array, Finding Duplicates
Difference Between File.Separator and Slash in Paths
How to Call the Default Deserializer from a Custom Deserializer in Jackson
How to Read a Specific Line Using the Specific Line Number from a File in Java
Java Error: Implicit Super Constructor Is Undefined for Default Constructor