So my first assignment involves making a simple question and answer program. The user asks a question, and I generate an answer. I've never done java before. Here is my input class:
//msg is the msg I output (answer to their question).
//Function returns inputStr which is the question the user asks.
public String getInput(String msg) {
System.out.println(msg);
Scanner theInput = new Scanner(System.in);
String inputStr = theInput.nextLine(); //ERROR HERE ON 2nd ITERATION!
theInput.close();
if (inputStr.equals("exit")) {
System.out.println("GoodBye!");
System.exit(0);
}
return inputStr;
}
The function that calls this in the while loop is as follows:
//inputSource is an object that has the getInput method. It is an argument for this function.
String userQuestion = inputSource.getInput(firstLine);
String initMsg = processMessage(userQuestion);
while(!initMsg.equalsIgnoreCase("GoodBye")){
userQuestion = inputSource.getInput(initMsg);
//Doesn't get to here.
initMsg = processMessage(userQuestion);
}
System.out.println(initMsg);
Error:
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1516)
So basically, what happens is that it asks a question once, and then it gives back an answer once, but when it enters the while loop, it gets stuck at the indicated point.
Little help. Thank you.
One thing that I noticed: you should probably not call close() on the scanner. You're closing the underlying input stream (standard input), according to the JavaDocs.
Related
I have a command-line game and am testing with JUnit, this is the test:
#Test
public void testBattle() throws IOException{
String input = "go forward\ngo left\ntake Pointy Stick\ngo backward\ngo " +
"right\nnormal attack\nnormal attack\nquit\n";
provideInput(input);
actual = new File("src/main/testFiles/testBattle.txt");
expected = new File("src/main/testFiles/testBattleExpected.txt");
PrintStream o = new PrintStream(actual);
System.setOut(o);
ui.gameLoop();
assertTrue(FileUtils.contentEqualsIgnoreEOL(actual, expected, null));
}
And this is the provide input method:
private void provideInput(String data) {
String newdata = data.trim();
testIn = new ByteArrayInputStream(newdata.getBytes());
System.setIn(testIn);
}
I'm doing scanner nextline so:
command = input.nextLine().toLowerCase().trim();
where "input" here represents the scanner object
but I'm still getting this error, specifically when the first "normal attack" is passed into System.in
java.util.NoSuchElementException: No line found
on that line above. I thought nextline ignored whitespace? If not did I format my string wrong to not include it?
EDIT:
From the first few lines of UI.gameLoop() I only initialize the scanner once.
public void gameLoop() throws IOException, JsonSyntaxException {
input = new Scanner(System.in);
engine = new GameEngine(path);
I thought nextline ignored whitespace?
Nope. According to the javadocs, it reads past the next end-of-line sequence (or to EOF), and then returns everything up to but not including the end-of-line sequence.
If you are getting
java.util.NoSuchElementException: No line found
that means that the Scanner has already reached the end of the input stream, or (maybe) the Scanner is trying to read from an input stream that was prematurely closed somewhere else in your code.
We can make guesses about what the real problem is, but without seeing >>your<< minimal reproducible example, we can't take this much further.
Actually, I just spotted a clue:
... I am testing with JUnit ...
This is possibly at the root of your problems. A JVM can only "read to the end of System.in" once in its lifetime. If you have two or more JUnit tests that need to do this, it is going to be difficult, unless you can find a way to "mock" the System.in variable.
It may be simpler to reorganize your code so that you take the input from some stream that is passed to your game code as a parameter. By reorganizing you can make it easier to write unit tests.
There's not a lot to go on, but I'm guessing you're creating multiple Scanners, one for each time you want to read a line. This usually works ok interactively since humans are slow typers, but fails when each Scanner's readahead ends up consuming multiple lines.
You can see the difference in this MCVE:
import java.util.*;
import java.io.*;
class Foo {
public static void main(String[] args) throws Exception {
String newdata = "go forward\ngo left\ntake Pointy Stick\ngo backward\ngo " +
"right\nnormal attack\nnormal attack\nquit\n".trim();
ByteArrayInputStream testIn = new ByteArrayInputStream(newdata.getBytes());
System.setIn(testIn);
boolean includeBug = Boolean.valueOf(args[0]);
if (includeBug) {
for(int i=0; i<8; i++) {
Scanner input = new Scanner(System.in);
System.out.println("Read: " + input.nextLine());
}
} else {
Scanner input = new Scanner(System.in);
for(int i=0; i<8; i++) {
System.out.println("Read: " + input.nextLine());
}
}
}
}
When includeBug is true, it creates a new Scanner for each line and crashes like you say. If it's false, it creates a single Scanner and works correctly:
$ javac Foo.java
$ java Foo true
Read: go forward
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Scanner.java:1540)
at Foo.main(Foo.java:17)
$ java Foo false
Read: go forward
Read: go left
Read: take Pointy Stick
Read: go backward
(etc)
Are you checking if it has a next line? With Scanners, you usually either have to handle the exception (not really something I'd prefer) or you have to use the hasNextLine() method to avoid the exception.
while (input.hasNextLine()) {
command = input.nextLine().toLowerCase().trim();
}
This is the basic setup for a little console-based quiz game. The answers are numbered. I want the player to give the answer number. If the input is not a number, then my program should give a warning, and wait for proper input.
Instead, what I get (after inserting something that is not a number) is an infinite loop of asking the question and presenting the answers again.
public static void main(String[] args) {
boolean quizActive = true;
while(quizActive) {
presentQuestion();
presentAnswers();
Scanner s = new Scanner(System.in);
if (s.hasNext()) {
String choice = s.next();
if (!NumberUtils.isNumber(choice)) {
presentText("Please insert the answer number.");
} else {
System.out.println("You made a choice!");
checkAnswer(choice);
quizActive = false;
}
s.close();
}
}
}
What am I doing wrong here?
If you do not want to question and answers be presented each time move presentQuestion() and presentAnswers() outside the loop.
But main problem is that you closing Scanner.
Remove s.close(); and move Scanner s = new Scanner(System.in); outside of the loop.
I really don't get the point in using scanner for acquiring user input.
The scanner class is perfect to process structured input from a flat file with known structure like an CSV.
But user input need to deal with all the human imperfection. After all the only advantage you get is not needing to call Integer.parseInt() your yourself at the cost to deal with the not cleared input when scanne.nextInt() fails...
So why not using InputStreamReader aside with a loop suggested by others?
Here an Example :
public class Application {
public static void main(String [] args) {
System.out.println("Please insert the answer number. ");
while (true) {
try {
Scanner in = new Scanner(System.in);
int choice = in.nextInt();
System.out.println("You made a choice!");
checkAnswer(choice);
break;
} catch (Exception e) {
System.out.println("Invalid Number, Please insert the answer number ");
}
}
}
}
You started your Quiz in a loop which is regulated by your quizActive boolean. That means that your methods presentQuestion() and presentAnswers() get called every time the loop starts again.
If you don't input a number but a character for example, your program will run the presentText("Please insert the answer number.") and start the loop again. As it starts the loop again, it will call the methods presentQuestion() and presentAnswers().
To stop that, you can do another loop around the input-sequence. Also your Scanner s = new Scanner(System.in) should be outside the loop. And you shouldn't close your Scanner right after the first input and then open it again!
if you want a code example, please tell me :)
I have Java code that asks for user input and then stores this data in a string variable. The below function is part of a class called 'number' and is called in the main function.
public static void setVal(int i){
Scanner readIn = new Scanner(System.in);
//while (readIn.hasNextLine()){
str = readIn.nextLine();
numCheck = false;
if (i == 1){
while (!numCheck){
if (str.contains(" ")){
System.out.println("Please input a single item.");
str = readIn.nextLine();
}
else if (!isNumeric(str)){
System.out.println("Please input a valid number.");
str = readIn.nextLine();
}
else {
numCheck = true;
value = Double.parseDouble(str);
readIn.close();
}
}
readIn.close();
}
else if (i == 2){
while (!numCheck){
if (str.contains(" ")){
System.out.println("Please input a single item.");
str = readIn.nextLine();
}
else if (!isNumeric(str)){
System.out.println("Please input a valid number.");
str = readIn.nextLine();
}
else {
numCheck = true;
secondV = Double.parseDouble(str);
readIn.close();
}
}
readIn.close();
}
else {
System.out.println("An error has occurred.");
}
// }
readIn.close();
}
Part of the main function looks like this:
number input = new number();
for (int i = 1; i <= 2; i++){
input.setVal(i);
System.out.println("Now please input a second value for computing with the first.");
input.setVal(i);
}
I use the same function twice but handing it a different argument to distinguish assignment of the input to a different variable but when it runs a second time it throws a no line found error.
Applying some other advice you can see commented out I have added a 'hasNextLine()' check to check if the line exists before executing the code but this ends up at a 'Scanner closed' error even though I invoke a new instance of Scanner every time the function runs. I have also closed the scanner appropriately to ensure minimisation of errors.
I have no idea what's going wrong as I can create a Scanner in the main function and call '.nextLine()' as many times as requried without an error but when called again through a class method, I receive these errors.
Any help is appreciated, thanks in advance.
Scanner.close() documentation states that
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. If this scanner is already closed then
invoking this method will have no effect.
On closing scanner, you are also closing System.in input stream, so when you reopen the scanner it will not find any open input stream.
Refer : java.util.NoSuchElementException - Scanner reading user input
Better pass scanner object from outside method as argument and then close it in calling method only when you are done with it.
Just to point out, is your String object str Static?
If not then you can't use it in your static method. Better you remove the static from method declaration.
You have to close the scanner when everything is done.
You have closed the scanner inout stream readIn.close(); twice.
You are closing the stream before picking line by line from the file. So you have to close it once after all the instances that use readIn is finished.
This question already has an answer here:
How to use java.util.Scanner to correctly read user input from System.in and act on it?
(1 answer)
Closed 8 years ago.
I'm attempting to make a java function that returns an int inputted by the user, but won't return until the user inputs a valid number. Here's my initial model of the function:
public int getChoice(){
try{
return scan.nextInt();
}catch(Exception e){
return getChoice();
}
}
scan is declared by Scanner scan = new Scanner(System.in);
This function resulted in a Java.lang.stackOverflowError(hmm... this seems an appropriate website for that...). I figure this is because the function is being constantly called.
I've considered somehow using Integer.valueOf(scan.nextLine())', but the reason I haven't really done anything with it is because at some points, and I can't figure out what determines whether this happens or not, but pressing 'Enter' when the program is calling nextLine() will skip the next nextLine(). I can't really figure out a way around that.
So if anyone could possibly provide me with a Java function that will loop until the user inputs a valid integer, then return that integer, please do so, thank you.
You are getting a bad recursion because the getChoice call inside catch block. To repeat the code indefinitely until the user gives you a valid number use while(true) infinite loop. The code you have to read the line and convert it to Integer it is just fine.
public int getChoice() {
while (true) {
try {
return Integer.valueOf(scan.nextLine());
} catch (Exception e) {
System.out.println("Enter a valid number");
}
}
}
I'm a oversea student. I use blueJ do my assessment. My code could run in terminal well, but after I submit my assessment the page response fails and shows
java.util.NoSuchElementException: No line found
My code:
public void input() {
Scanner keyboard = new Scanner(System.in);
System.out.print("Move (l/r/u/d): ");
String name = keyboard.nextLine();
if(name.equals("l")) {
move(-1,0);
}
else if(name.equals("r")) {
move(1,0);
}
else if(name.equals("u")) {
move(0,-1);
}
else if(name.equals("d")) {
move(0,1);
}
else {
System.out.println("Invalid move");
}
}
I suggest that you read the requirements for your assignments again carefully.
The symptoms clearly indicate that your program is being tested in a context in which there is no input to be read from System.in. The most obvious explanation is that your program is supposed to be getting its input some other way. But unless we see the requirements, we cab only guess what it is supposed to do.
I guess another possibility is that the program that is testing your assignment code is faulty.
By seeing the error line not found,u replace print() into println().