I have started learning Java recently. I was learning to take user input using Scanner class when I Started getting an error. Here is the code:
Scanner userInput1 = new Scanner(System.in);
String name = userInput1.nextLine();
System.out.println("Hi "+ name);
userInput1.close();
Scanner userInput2 = new Scanner(System.in);
int age = userInput2.nextInt();
System.out.println(age);
I get the following error when I enter "Deadboy" as input:
Hi Deadboy
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
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 com.first.Main.main(Main.java:17)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Process finished with exit code 1
I am unable to enter the value for "age".
If, however, I comment the line "userInput1.close()", the code works.
What is the problem?
I am sorry if this question has been answered before. I found a similar question but I was not sure if its answers were the ones I was looking for.
There's a couple of problems here.
First, you do not want to close the System.in stream. Other parts of the program may be using it, and you don't want to interfere with their normal operation.
Second, there's no benefit to creating more than one Scanner object. It's simply reading input from a stream, and having more than one reference to that stream isn't necessary or beneficial to your operations.
To that end, the fix to this would be straightforward:
Use only one instance of the Scanner attached to System.in, and
Remove the close() method call.
The problem here is that when you are closing Scanner userInput1, it closes input source, with which it was created - in this case it is InputStream you got from accessing System.in.
So when you call
Scanner userInput2 = new Scanner(System.in);
at this point System.in InputStream is already closed, and you can not longer work with it.
There is actually no need to create Scanner object each time you want to read something from console. You can use the same Scanner object
Scanner scanner = new Scanner(System.in);
String name = scanner.nextLine();
System.out.println("Hi "+name);
int age = scanner.nextInt();
System.out.println("Age :" + age);
Several things. First of all, you do not need to make two Scanner objects. You can use one scanner object to scan in everything, the way you're using it. Two, there's no point in closing the scanner the way you're doing it. Why are you closing the scanner? Fix those, and run the codes again.
Related
I want to output a question to the console and then get the next line of input after the question was output.
For example, my program could be sleeping or doing some time-consuming computation, and while the user is waiting they might decide to type some notes into the console (perhaps without hitting enter, or perhaps over several lines). Once the sleep is completed, the program then asks the user a question, "What is your name?" and then it should wait for the next line of input containing the user's name, and ignore any random notes the user made while the sleep was going on.
Here's some code that tries to do that:
public static void main(String[] args) throws InterruptedException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
// while (scanner.hasNext()) {
// scanner.nextLine();
// }
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
This behaves as follows when I type a couple of lines during the sleep:
gpeo
hpotWhat is your name?
Hi, gpeo
The problem is that scanner will read the next input continuing from the last input it read, not from the last System.out.println() (which makes sense). The commented out code tries to rectify that problem by reading past all earlier input first, then waiting on one more line to assign to name. However, scanner.hasNext() does not work as I was hoping, since when there is no next token it does not simply return false but waits for another token (so I don't know why it bothers to return a boolean at all).
Another thing that baffles me is that during the sleep if you type stuff on a single line, that single does in fact get ignored:
brbr irgjojWhat is your name?
A
Hi, A
I thought it was going to output Hi, brbr irgjojA, so that makes me think I might be misunderstanding how console input and Scanner work.
Edit: The last example was from a run within IntelliJ. When I run from my Bash commandline instead I get Hi, brbr irgjojA. The output of the first example does not change though.
Also, I was asked if this question is the same as this, and apparently I have to explain why it's not here or it will appear on the question. The issue in that post (and others like it) is that he/she is mixing scanner.nextLine() with scanner.nextInt() and similar methods that do not read the whole line or the line ending. I am only using nextLine() to read input, and my issue is quite different.
Further edit
I managed to discard the first line of random notes based on this answer to another question. Here is the new code:
public static void main(String[] args) throws InterruptedException, IOException {
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
System.out.println("What is your name?");
while (System.in.available() > 0) {
scanner.nextLine();
}
String name = scanner.nextLine();
System.out.println("Hi, " + name);
}
Here are some test runs in IntelliJ:
grgWhat is your name?
A
Hi, A
ghr
rhWhat is your name?
A
Hi, A
rghr
hrh
htWhat is your name?
Hi, hrh
uirh
iw
hjrt
sfWhat is your name?
Hi, iw
And here are similar tests in Bash:
htrWhat is your name?
A
Hi, htrA
rgj
hrWhat is your name?
A
Hi, hrA
rjkh
ry
jWhat is your name?
Hi, ry
ryi
rj
rd
jrWhat is your name?
Hi, rj
As you can see, the line inside the while loop never appears to get executed more than once for some reason. I tried adding a sleep inside the loop or using other InputStream methods like skip() and readAllBytes(), but these didn't seem to help at all.
I think there might not be anything one can do about the incomplete line that is a problem for Bash, but I'm sure there must be a way to throw out all the completed lines (rather than just the first one). The solution doesn't have to use Scanner, it should just behave as intended.
The Scanner uses a buffer. It’s default size is 1024 characters. So by the first nextLine() call, it reads up to 1024 of the available characters into the buffer. This is necessary, as the Scanner doesn’t even know how many characters belong to the next line, before filling the buffer and searching for a line break in the buffer.
Therefore, if there are less pending characters than the buffer size, the loop will iterate only once. But even when there are more characters, and more loop iterations, the resulting state likely is to have some pending lines in the buffer.
As long as the Scanner’s buffer is in its initial empty state, you can flush the source stream directly, instead of using the scanner:
Scanner scanner = new Scanner(System.in);
Thread.sleep(10_000);
while(System.in.available() > 0) {
System.in.read(new byte[System.in.available()]);
}
System.out.println("What is your name?");
String name = scanner.nextLine();
System.out.println("Hi, " + name);
Note that it would be natural to use System.in.skip(System.in.available()); instead of read, but while trying it, I encountered a bug that the underlying stream did not update the available() count after a skip when reading from a console.
Note that if the Scanner is not in its initial state but has some buffered content already, there is no way to flush the buffer, as its API is intended to make no distinction between buffered and not yet buffered, so any attempt to match all content would result in reading from the source (and blocking) again. The simplest solution to get rid of the buffered content would be
scanner = new Scanner(System.in);
We need to make something of a lexical analyzer, and I have had some trouble with a particular function of mine, useLoad, or more accurately, what happens in Main after useLoad is used.
I figured out that that was because...for some reason, buffer=keyboard.nextLine() is throwing the error, because it's not getting more input from the keyboard for some reason. I thought that .nextLine() should force it to get more input from the user. And I don't know why it's throwing that exception specifically after this one particular method. It can do other methods just fine and not lose its ability to read. Is it because I have a variable called keyboard in another object and closed it? That seems doubtful. Just tried changing the name. Didn't make a difference.
Variables used but not declared in the below code: Keywords[0] is the String "load ". initial = the scanner string that's passed in to the function. offset = a counter variable, to see how far in to the line we've read.
The useLoad function (which is what I think is messing up somehow), is at the bottom, but I included everything it runs through (with each method separated by a horizontal rule), in chronological order, just in case I'm just not seeing what's going on.
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
int i = 0;
String buffer ="";
boolean loopControl == true;
SymbolTable mySym = new SymbolTable();
System.out.println("READY FOR INPUT\n");
while (loopControl == true){
//read in the line
buffer = "";
buffer = keyboard.nextLine();
if(!mySym.checkStop(buffer)){ //if we didn't stop
mySym.primary(buffer);
}
else{//if we did stop
closeLoop();
}
if (i >= 55){
loopControl = false;
System.out.println(("You have gone over the limit ("+i+" lines) per execution. Please continue by running this program again.").toUpperCase());
//just a safety precaution...you know... in case closeLoop doesn't work
}
i++;
}
keyboard.close();
}
if(initial.substring(0, Keywords[0].length()).equals(Keywords[0])){ //Load
//if this is working as expected, then we simply need to do what the keyword says to do.
offset += Keywords[0].length(); //we have moved this much deeper in to the line
useLoad(offset, initial);
offset = 0; //just make sure, once we are done with the line, we start back at the start of the next line.
return; //we found what we were looking for, get out.
}
private void useLoad(int offsetIn, String readIn) {
double doubIn = 0;
//now get the value of the
Scanner keyboard = new Scanner(System.in); //the scanner for keyboard
System.out.println("\nENTER VALUE FOR " + readIn.toUpperCase());
doubIn = keyboard.nextDouble();
keyboard.close();
variables.create(readIn.substring(offsetIn), doubIn);
}
I think I've figured out your problem.
Java docs for both Java 7 and 8 include this line in Scanner's close method documentation:
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.
Looking into the docs for System, I've found that System.in is of type InputStream which, you guessed it, implements Closeable. The close method documentation for InputStream says that it does nothing; however, InputStream is abstract and close is not marked as final, which means it can be overridden. System.in returns an InputStream which could potentially - and clearly does - do something.
So the problem is, you are creating multiple Scanners with System.in, and each time you close any one of them, you close System.in, rendering it useless!
This problem has actually been discussed in another question here, with a solution given. That said, for your program I would suggest one of two approaches:
The first approach is mentioned there: Either use a pre-made wrapper class or make your own, which accepts an InputStream in its constructor. Have this class' InputStream implementation call all the methods of its wrapped object, except for the close method which is a no-sell, and then pass Wrapper(System.in) to Scanner instead of System.in directly. However, I would be wary of taking this approach except in very specific circumstances, because any time you use one of these wrappers you would need to remember to close its wrapped object at the end of its use, unless it's something like System.in.
Second approach: Use a runner class in your program, and initialize the scanner there. Pass the scanner into the required objects during construction for them to hold a reference to, and then allow them to complete their required tasks without closing Scanner within the class. Once the exit condition is specified, return to the runner class and close Scanner from there.
You close the keyboard each time round the loop. Therefore the second time around you read from a closed keyboard object.
A quick look at the documentation for Scanner.nextLine contains the news that it might throw:
NoSuchElementException - if no line was found
I've been searching overflow questions and googling it for about half an hour and can't find an answer for this.
At first I thought it might be that I'm not closing my Scanner object. I added
inp.close();
after all my code,but still nothing.
I'm using Eclipse to create a simple Binary Search algorithm.
My problem is that it is not keeping my input. And what's even weirder is that it only accepts "5".
After pressing enter it only creates more spaces. It doesn't move on to the rest of the program.
I've also tried entering more values under the "skipped" ones without any success.
Here's some screenshots
nextInt() reads scans the next token of the input as an int.
If the input is not an int, then an InputMismatchException is thrown.
You can use next() to read the input, whatever its type is. And you can hasNextInt() to make sure the next input is an int:
Scanner inp = new Scanner(System.in);
if(inp.hasNext()) {
if(inp.hasNextInt()) {
int n = inp.nextInt();
// do something with n
} else {
String s = inp.next();
// do something with s
}
}
Actually, I have a theory - your Scanner code is working just fine, it's your binary search code that's broken. Whatever it's doing works on an input of 5 but falls into an infinite loop for other inputs.
Consider breaking up your input parsing code from your binary searching code (e.g. do input parsing in main() and define a binarySearch() function that main() calls) so that you can test them separately.
First I'm a noob to Java so don't be mad at me if I'm acting stupid - Thanks.
As I said I'm trying to learn Java. Right now I'm trying to learn the right scanner for this mini-game, but I'm getting confused because people tell me to do it in two different ways. I just wan't to know which one to use and where I can use the other one.
First Example:
Scanner input = new Scanner(System.in);
Second Example:
Scanner input = new Scanner(System.in);
String userInput = input.nextLine();
Please tell me how to make the " right " scanner for my mini-game and explain when I should use the other one.
If you know which one to use, another way to create a scanner for this or just wanna share the scanners and how to use them - then please add it as an answer.
Scanner input = new Scanner(System.in);
This is calling a scanner and telling that it should be used in the console "System.in".
String userInput = input.nextLine();
This line is taking the value u inserted in the console and saving in a variable named "userInput"
You can add this System.out.println("the inserted value is : " + userInput);
And it will print in the console the value you inserted
If I'm reading your question correctly, both of your examples are same as far as creating a Scanner object is concerned. Only difference is that second example is also storing the nextLine of input into a String variable called userInput.
Look here to understand Scanner class better:
http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
Dear Secretive Hackers and Legendary Programmers,
I already know that the scanner is used to recognize user input much like the java bufferedreader in the io section of the virtual java handbook. The question is how can you apply the scanner in the simplest terms, meaning beginning with a set button such as {A} or say {1} for instance? How do I apply the scanner to get java to realize these buttons were pressed, and if so, then print the set condition?
Logic:
Scanner application??... (I need help with this)
If A, then System.out.println("Hi, my name is A!!")
If 1, then System.out.println("Hi, my name is 1!!")
Thanks much
To the extent of my (somewhat limited) knowledge, a Scanner reading System.in will not pass any data until the enter (return) key is pressed (as until that point, it has no data to pass), so it would not respond to lone button presses. It will respond if you do press enter, so use something like:
Scanner yourScanner = new Scanner(System.in);
//Creates a scanner that reads from the terminal.
System.out.println("What is my name? ");
//Whatever you want the user to be asked, let them know what to input.
String theirResponse = scan.next();
//Or .nextLine() if the input contains a space in the middle
System.out.println("Hi, my name is " + theirResponse + "!!");
//Prints out and uses their response.
Unfortunately, Scanner is not a very good way to go for key listening.