I am having a problem while using a Scanner and I do not know how to solve it, kind of new in Java. I have created a menu to read an input char provided by the user through a Scanner and I read options from the menu with this loop:
/**
* Constant to exit the menu.
*/
private static final char EXIT = 'E';
public void run() {
char option = EXIT;
do {
menu.show();
option = menu.readOption();
try {
processOption(option);
} catch (RuntimeException exception) {
handleSystemError(exception);
} catch (Exception exception) {
handleUserError(exception);
}
} while (option != EXIT);
}
This is what the method readOption does :
public char readOption() {
return Console.readChar(" Option ");
}
And this is what the method readChar does :
public static char readChar(String msg) {
out.println( msg + ": ");
keyboard.useDelimiter(System.lineSeparator());
char res = keyboard.next().charAt(0);
keyboard.reset();
return res;
}
The problem is, the loop in its first performance works perfectly fine. The program works propperly. But after the first performance, when it starts again, in the line where it readsOption, it throws a NoSuchElementException and I have been many hours trying to solve it and I do not know how to. Apparently the problem is in the method readChar, when I try to do "keyboard.next()" it throws the no such element exception. Cannot explain that it works the first time and not a second one. When first performance, it waits for me to introduce a char as I expect, but in the second one,while I wish to be expected to introduce a char, when "keyboard.next()", it throws the mentioned exception. Having an issue clearly with my Scanner, I hope someone can identify the issue here. Thank you very much everyone.
I finally found how to solve it thanks to this page: Solucione el error NoSuchElementException en Java
The issue was that because of the size of this program I had to use 2 scanners at the same time, and when I closed one of them, it caused the other one to stop working, throwing that exception.
Related
I have an assignment that requires me to write a program in JAVA with 10 different methods including the main. It obtains the input from a file in order to extract data from a second file through the various methods. Lastly it prints the results to a third file. THis is an intro class and we were insturcted to use the hasNext method. THe second file where the data is retrieved from has 10 rows and 5 columns, each column representing something different. I used sc1.nextInt() since our professor warned us that the programs will read every piece of data and we havent learned how to extract data from just one column. I am stuck on an error I keep receiving. I have included a snippet of my code if anyone can help me. Thank you.
this is the error I keep receiving:
Exception in thread "main"
java.util.InputMismatchException at
java.util.Scanner.throwFor(Scanner.java:864) at
java.util.Scanner.next(Scanner.java:1485) at
java.util.Scanner.nextInt(Scanner.java:2117) at
java.util.Scanner.nextInt(Scanner.java:2076) at
homework4.HomeWork4.checkNumber(HomeWork4.java:47) at
homework4.HomeWork4.main(HomeWork4.java:26)
/Users/xiomarahenriquez/Library/Caches/NetBeans/8.2/executor-snippets/run.xml:53:
Java returned: 1 BUILD FAILED (total time: 0 seconds)"
public static PrintStream ps;
public static void main(String[] args) throws Exception {
ps = new PrintStream("elementsResults.txt");
Scanner sc1 = new Scanner(new File("input.txt"));
int atomicNumber, valid=0, invalid=0, totalProcessed=0;
while (sc1.hasNext()) {
atomicNumber = sc1.nextInt();
checkNumber(atomicNumber);
if(checkNumber(atomicNumber)== true){
++valid;
} else {
++invalid;
}
++totalProcessed;
}
}
public static boolean checkNumber (int atomicNumber) throws Exception {
Scanner sc2 = new Scanner (new File("PeriodicTable.txt"));
int columnA = sc2.nextInt();
String columnB;
int columnC,columnD,columnE;
while (sc2.hasNext() && (columnA > -1 || columnA < 118)) {
columnA=sc2.nextInt();
columnB=sc2.next();
columnC=sc2.nextInt();
columnD=sc2.nextInt();
columnE=sc2.nextInt();
if (atomicNumber==columnA) {
return true;
}
}
sc2.close();
return false;
}
I think that the cause of your problem is in the first line of your exception stack trace:
Exception in thread "main" java.util.InputMismatchException
Here's a link to the documentation for the InputMismatchException. I can't say for sure since I don't know what your input files look like but I'm pretty sure that when you're calling nextInt(), the next token read isn't something that can be cast to an int. My guess is that the Scanner is encountering some text or something else preventing it from returning an int. To figure out which token is causing the problem, I'd try wrapping your invocations of nextInt() in try/catch blocks. When the Scanner throws an InputMismatchException, it will not pass the token that caused the exception so that after the exception is thrown you can get the value of the token (like with the next() method) or skip the token altogether. Here's an example (I don't have access to an IDE right now so this isn't tested but hopefully you can get the idea):
//Some initialization code here...
Scanner myScanner = new Scanner(new File("myFile.txt"));
while(myScanner.hasNext()) {
try {
int myIntVariable = myScanner.nextInt();
} catch (InputMismatchException ex) {
System.out.println("Here's the token that caused the problem: " + myScanner.next());
}
}
//The rest of your code here...
By the way, if you're not absolutely sure that the token that you're retrieving is the type that you think it's going to be (in your case an int), it's probably a good idea to wrap that portion of the code in a try/catch block so that you can handle cases where the token isn't what you think it is.
This is my first answer. Hope it helps.
In your while loop you are running the checkNumber method twice. That's unnecessary. Do it just once like below. Also there is a slight difference between ++i and i++ so check this link: what is the difference between i++ & ++i in for loop (Java)?
while (sc1.hasNext()) {
atomicNumber = sc1.nextInt();
if(checkNumber(atomicNumber)== true){
valid++;
} else {
invalid++;
}
totalProcessed++;
}
This question already has answers here:
Endless while loop problem with try/catch
(2 answers)
Closed 7 years ago.
Below code,
import java.util.Scanner;
public class Dummy {
static Scanner sc = new Scanner(System.in);
public static int getIntegerInput(String prompt){
int choice = 0;
for(;;){
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
}catch(java.util.InputMismatchException ex){
System.out.print("What??? ");
}
}
return choice;
}
public static void main(String[] args) {
int choice = getIntegerInput("Enter a number: ");
} //end main
}
does not stop for next user input, if the first user input raised an exception.
How do I understand this problem in the above code? placing sc.next() in catch resolves the problem. But I'm still not clear what is going on under the hood? What is the right approach to resolve this problem?
When nextXYZ() fails to consume a token it leaves it in the InputStream. Here, you are looping over the same input endlessly - each iteration, you attempt to consume this token, throw an exception if it isn't an integer, catch it, and try reading it again - forever.
EDIT:
In order to work around this, you could use next() to consume that token and move on to the next one:
for(;;) {
System.out.print(prompt);
try{
choice = sc.nextInt();
break;
} catch(java.util.InputMismatchException ex) {
sc.next(); // here
}
}
The problem with Scanner next() are they will not advances if the match is not found. And the character for which it failed remain in the stream. Hence its very important to advance the scanner if you found non intended character.
You can use next() method which actually consumes any character or you can use skip method passing skip pattern.
Use hasNext() to know whether a valid match is present or not. If not then consume that character using above said methods.
If it doesnt find an int on the next like, it throws an error. This error is then caught by your program, so the break is never hit because the error jumps over it whenever a non-int (including nothing) is found.
I read in a menu choice and typing in any number but 2 & 5 work.
String choice = promptUser(choicePrompt);
try {
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
public static void outputInfo(String msg)
{
System.out.printf("\t%s\n",msg);
}
Good output:
Enter Option: 1
choice=...1...
Bad Output:
Enter Option: 2
choice=...2...
choice=2
java.lang.NumberFormatException: For input string: ""
Update:
I've hard-coded "2" and it still fails!:
String choice = promptUser(choicePrompt);
try {
choice="2";
outputInfo(String.format("choice=...%s...",choice));
int c = Integer.parseInt(choice);
/* process it */
}catch (NumberFormatException e) {
outputInfo(String.format("choice=%s",choice));
outputInfo(e.toString());
}
Hard-coding "5" also fails but "1" works!!!
Any ideas gratefully received.
Simon
If I assume your promptUser() method to be something like:
static String promptUser() {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
try {
return reader.readLine();
}
catch(Exception ex) {
return null;
}
}
(without the parameter) then the program behaves as expected - certainly there's nothing in that code that treats 2 or 5 differently. If you're getting an empty string then are you sure your prompt user method is working correctly?
Either way, the code you've posted here is essentially correct. I would imagine there's something else wrong in your more fully complete program that doesn't manifest itself when you've reduced it down here; perhaps you're running into a case where a local variable is hiding a field for example and you're not using the value you think you are (but at this point, I'm just guessing.)
updated
Seems the promptUser method is returning an empty String "". check if choice is empty before calling
ParseInt method
Also you can add trim() to eliminate spaces before and after the input
if(choice!=null && !"".equals(choice))
int c = Integer.parseInt(choice.trim());
printStackTrace() is your friend.
Turns out the number format exception was further down (in the 'process it' code) and was not being caught down there.
It was data driven so didn't happen on other machines.
Thanks to every one for your support.
Simon
I apologize since I'm always asking n00b questions but I could really use the help. Anyways I'm trying to import words of only a certain length from the dictionary into the variable words which is a hash set. When I run my program and try to print my words aka the hashset of strings. I get nothing in the console and the program does not stop running. How can I fix this? P.S. Also I know part of the JOptionPane code got cut enough, but it's error free and you get the point. Thanks!
Alex
public void inputWords()
{
try
{
frame = new JFrame("Hangman");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300,300);
frame.setVisible(true);
input = new Scanner(new FileInputStream("dictionary.txt"));
wordLength = Integer.parseInt( JOptionPane.showInputDialog(null,
String importedWords = input.nextLine();
while(stillHasWords==true)
{
if(importedWords.length()==wordLength)
{
words.add(importedWords);
}
else
{
}
}
}
catch(FileNotFoundException f)
{
System.out.println("File does not exist.");
System.exit(0);
}
catch(NoSuchElementException q)
{
stillHasWords=false;
}
public static void main(String[] args)
{
EvilHangman j = new EvilHangman();
System.out.println(stillHasWords);
j.inputWords();
System.out.println(words + " ");
}
}
Regarding:
while(stillHasWords==true)
{
if(importedWords.length()==wordLength)
{
words.add(importedWords);
}
else
{
}
}
I'm not sure what words.add(importedWords) does, but most important to the problem you're experiencing,
Question: Where do you change stillHasWords inside of your loop?
Answer: You don't, and so the loop will never end.
I suggest that first you fix this while loop
As an aside, it's better to avoid using == true in a while loop and instead simply test the boolean:
while (stillHasWords) {
// add a word
// change stillHasWords to false if we've run out of words
}
Edit
You state:
Still has words changes in the catch(NoSuchElementException q)
There is no catch block posted inside of the while loop, and so I submit that still the stillHasWords value cannot change inside of the while loop based on code you've posted so far. If you have more pertinent code, then you'll of course want to show it, else we're reduced to guessing what might be wrong with code not shown. Best to post an SSCCE
So here is my code:
public static void getArmor(String treasure)
throws FileNotFoundException{
Random rand=new Random();
Scanner file=new Scanner(new File ("armor.txt"));
while(!file.next().equals(treasure)){
file.next(); //stack trace error here
}
int min=file.nextInt();
int max=file.nextInt();
int defense=min + (int)(Math.random() * ((max - min) + 1));
treasure=treasure.replace("_", " ");
System.out.println(treasure);
System.out.println("Defense: "+defense);
System.out.println("=====");
System.out.println();
}
public static void getTreasureClass(Monster monGet)
throws FileNotFoundException{
Random rand = new Random();
String tc=monGet.getTreasureClass();
while (tc.startsWith("tc:")){
Scanner scan=new Scanner(new File ("TreasureClassEx.txt"));
String eachLine=scan.nextLine();
while(!tc.equals(scan.next())){
eachLine=scan.nextLine();
}
for (int i=0;i<=rand.nextInt(3);i++){
tc=scan.next();
}
getArmor(tc); //stack trace error here
}
}
For some reason I get a No Such Element Exception
at java.util.Scanner.throwFor(Scanner.java:907)
at java.util.Scanner.next(Scanner.java:1416)
at LootGenerator.getArmor(LootGenerator.java:43)
at LootGenerator.getTreasureClass(LootGenerator.java:68)
at LootGenerator.getMonster(LootGenerator.java:127)
at LootGenerator.theGame(LootGenerator.java:19)
at LootGenerator.main(LootGenerator.java:11)
I'm not sure why though. Basically my program is searching through two text files - armor.txt and TreasureClassEx.txt. getTreasureClass receives a treasure class from a monster and searches through the txt until it reaches a base armor item (a string that does not start with tc:.) It then searches getArmor for an armor that matches the name of the base armor it got in treasure class. Any advice would be appreciated! Thanks!
The link to the txt files is here: http://www.cis.upenn.edu/~cis110/hw/hw06/large_data.zip
It looks like you are calling next even if the scanner no longer has a next element to provide... throwing the exception.
while(!file.next().equals(treasure)){
file.next();
}
Should be something like
boolean foundTreasure = false;
while(file.hasNext()){
if(file.next().equals(treasure)){
foundTreasure = true;
break; // found treasure, if you need to use it, assign to variable beforehand
}
}
// out here, either we never found treasure at all, or the last element we looked as was treasure... act accordingly
I had run into the same issue while I was dealing with large dataset. One thing I've noticed was the NoSuchElementException is thrown when the Scanner reaches the endOfFile, where it is not going to affect our data.
Here, I've placed my code in try block and catch block handles the exception. You can also leave it empty, if you don't want to perform any task.
For the above question, because you are using file.next() both in the condition and in the while loop you can handle the exception as
while(!file.next().equals(treasure)){
try{
file.next(); //stack trace error here
}catch(NoSuchElementException e) { }
}
This worked perfectly for me, if there are any corner cases for my approach, do let me know through comments.
Another situation which issues the same problem,
map.entrySet().iterator().next()
If there is no element in the Map object, then the above code will return NoSuchElementException. Make sure to call hasNext() first.
Looks like your file.next() line in the while loop is throwing the NoSuchElementException since the scanner reached the end of file. Read the next() java API here
Also you should not call next() in the loop and also in the while condition. In the while condition you should check if next token is available and inside the while loop check if its equal to treasure.
I Know this question was aked 3 years ago, but I just had the same problem, and what solved it was instead of putting:
while (i.hasNext()) {
// code goes here
}
I did one iteration at the start, and then checked for condition using:
do {
// code goes here
} while (i.hasNext());
I hope this will help some people at some stage.