Scanner HasNextLine always returns false - java

I'm facing this weird problem with Scanner.hasNextLine().
I'm not used with the Scanner class but I'm used to use Scanner.hasNextLine() as a condition for a loop to get continuously user's input but in this part of code it always returns false !
public static void main(String[] args) throws IOException {
String s = "";
Scanner ssc = new Scanner(System.in);
Client cli = new Client();
cli.HLO();
Thread t = new Thread(new ThreadMessage(cli));//Thread that asks user for input using Scanner and closing it then
t.start();
boolean b = ssc.hasNextLine();
while (true) {
b = ssc.hasNextLine();
System.out.println(b);
if (b) {
s = ssc.nextLine();
System.out.println("you wrote" + s);
cli.dp.setData(s.getBytes());
cli.ds.send(cli.dp);
}
}
}
and as is an input I only have a loop of lines with the word false
Does anybody have an idea why it behaves so?
EDIT: Seems that the errors comes froms HLO function that uses another Scanner I removed it and it words properly now.

Try to use the .hasNext() method instead of using the .hasNextLine() method.
You are having problems because the .hasNextLine() method returns true if there is another line in the input of this scanner. But the .hasNext() method returns true if this scanner has another token in its input.
Refer : http://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html

In my case I have multiple Scanner(System.in) instances in a code which is touched by several people.
If one of those instances call "close", it will closed for all and the file is not reopened.
After the call to close hasNextLine() always will return false.

Related

Scanner.hasNextLine - always true

I need to read data from standard input.
And I want to print it to standard output.
I use Scanner for this:
import java.util.Scanner;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
int countLines = 1;
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
sb.append(countLines).append(" ").append(line);
}
System.out.println("finish");
System.out.println(sb.toString());
scanner.close();
}
I input this data:
Hello world
I am a file
Read me until end-of-file.
But hasNextLine()) is always true. And as result never print "finish"
Your code seems to work fine. Are you sure you output EOF correctly? Try Ctrl+D (Cmd+D on Mac) or Ctrl+Z on Windows, as mentioned here: How to send EOF via Windows terminal
There is no condition in which the loop will be false, it'll read the lines forever and ever. Consider adding a stop keyword like "stop"
while(scanner.hasNextLine())
{
String line = scanner.nextLine();
if(line.equalsIgnoreCase("stop"))
{
break;
}
//whatever else you have in the loop
}
Unless you stop it, it'll always be true. As pointed out by #Aaron
Scanner.hasNextLine() blocks waiting for a new line, it will only return false if you close the stream (using Ctrl-Z or D as Liel mentions in his answer)

Scanner gets skipped

I'm trying to get 2 integers from the user. This is the related part of my code:
public void play() {
int row=0,col=0;
initializeboard();
printboard();
do {
currentPlayer = players.remove(); //Returns currentPlayer
System.out.println("Ok, "+ currentPlayer.getname() + ", Enter your Move: Row[1-3] & Column[1-3]");
Scanner choice = new Scanner(System.in);
if (choice.hasNext()) {
row = choice.nextInt();
col = choice.nextInt();
while (row<1 || row>3 || col<1 || col>3 || board[row-1][col-1] != '-' ) {
System.out.println("Well, Move is not Valid or has already Been Selected, Try Again :/");
row = choice.nextInt();
col = choice.nextInt();
}
choice.close();
}
board[row][col] = currentPlayer.getsign(); //Places Sign in Game Board
printboard();
System.out.println();
players.append(currentPlayer); //Inserts the Next Player
} while(!win() && !isFull());
}
At first, it throws a NoSuchElementException, so I used .hasNext(). Now, it just skips the scanner and immediately invokes printboard().
The problem is that you are creating and then closing multiple Scanner objects with the same stream.
The answer from Peter Lawrey in this post explains why you shouldn't create multiple Scanner objects from the same stream. Here is a quote from the answer:
Once you close a stream it closes the underlying stream and you can't use it again. Only close System.in if you want to prevent it being used again.
The best thing is to create one final Scanner object (per stream) in your program and just pass it into methods when you want to use it:
static final Scanner scan = new Scanner(System.in);
Here is the problem :
do {
Scanner choice = new Scanner(System.in);
[...]
choice.close();
} while (!win() && !isFull());
You are opening a Scanner in a loop (first mistake) but more important, you are closing the Scanner.
Closing a Scanner also close the InputStream used, in your case System.in. You can't open that stream again so you will never be able to execute your loop twice.
public void 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.
And this is in fact the problem you are facing. Once you have closed the first Scanner created and then try to open a new one, since System.in is closed, there is no value to read (hasNext return false). And you most likely enter an infinite loop since !win() && !isFull() will always give the same result.
I suggest not close it (in this case, this is not always a bad thing since it is a local variable, there is no risk).
Or simply use a parameter in the method to provide it (and still not closing it in the method). Let the main method manage the Scanner.
public void play(Scanner choice){
...
}
It might have been throwing the NoSuchElementException because you didn't input a integer.
The reason it "skips" over the Scanner is possibly because all hasNext evalutes is whether the System.in has a String contained in it. So it evalutes that expression and returns true or false. Your program then evaluates the expression in the while loop, possibly finding it to be false. Then finally moving on and invoking printboard.
I would suggest going back and changing hasNext to
row = choice.nextInt();
col = choice.nextInt();
Then make sure you are inputting integers.

Scanner.next() and hasNext() creating infinite loop when reading from console [duplicate]

I ran into an issue. Below is my code, which asks user for input and prints out what the user inputs one word at a time.
The problem is that the program never ends, and from my limited understanding, it seem to get stuck inside the while loop. Could anyone help me a little?
import java.util.Scanner;
public class Test{
public static void main(String args[]){
System.out.print("Enter your sentence: ");
Scanner sc = new Scanner (System.in);
while (sc.hasNext() == true ) {
String s1 = sc.next();
System.out.println(s1);
}
System.out.println("The loop has been ended"); // This somehow never get printed.
}
}
You keep on getting new a new string and continue the loop if it's not empty. Simply insert a control in the loop for an exit string.
while(!s1.equals("exit") && sc.hasNext()) {
// operate
}
If you want to declare the string inside the loop and not to do the operations in the loop body if the string is "exit":
while(sc.hasNext()) {
String s1 = sc.next();
if(s1.equals("exit")) {
break;
}
//operate
}
The Scanner will continue to read until it finds an "end of file" condition.
As you're reading from stdin, that'll either be when you send an EOF character (usually ^d on Unix), or at the end of the file if you use < style redirection.
When you use scanner, as mentioned by Alnitak, you only get 'false' for hasNext() when you have a EOF character, basically... You cannot easily send and EOF character using the keyboard, therefore in situations like this, it's common to have a special character or word which you can send to stop execution, for example:
String s1 = sc.next();
if (s1.equals("exit")) {
break;
}
Break will get you out of the loop.
Your condition is right (though you should drop the == true). What is happening is that the scanner will keep going until it reaches the end of the input. Try Ctrl+D, or pipe the input from a file (java myclass < input.txt).
it doesn't work because you have not programmed a fail-safe into the code. java sees that the scanner can still collect input while there is input to be collected and if possible, while that is true, it keeps doing so. having a scanner test to see if a certain word, like EXIT for example, is fine, but you could also have it loop a certain number of times, like ten or so. but the most efficient approach is to ask the user of your program how many strings they wish to enter, and while the number of strings they enter is less than the number they put in, the program shall execute. an added option could be if they type EXIT, when they see they need less spaces than they put in and don't want to fill the next cells up with nothing but whitespace. and you could have the program ask if they want to enter more input, in case they realize they need to enter more data into the computer.
the program would be quite simplistic to make, as well because there are a plethera of ways you could do it. feel free to ask me for these ways, i'm running out of room though. XD
If you don't want to use an EOF character for this, you can use StringTokenizer :
import java.util.*;
public class Test{
public static void main(){
Scanner sc = new Scanner (System.in);
System.out.print("Enter your sentence: ");
String s=sc.nextLine();
StringTokenizer st=new StringTokenizer(s," ");//" " is the delimiter here.
while (st.hasMoreTokens() ) {
String s1 = st.nextToken();
System.out.println(s1);
}
System.out.println("The loop has been ended");
}
}
I had the same problem and I solved it by reading the full line from the console with one scanner object, and then parsing the resulting string using a second scanner object.
Scanner console = new Scanner(System.in);
System.out.println("Enter input here:");
String inputLine = console.nextLine();
Scanner input = new Scanner(inputLine);
List<String> arg = new ArrayList<>();
while (input.hasNext()) {
arg.add(input.next().toLowerCase());
}
You can simply use one of the system dependent end-of-file indicators ( d for Unix/Linux/Ubuntu, z for windows) to make the while statement false. This should get you out of the loop nicely. :)
Modify the while loop as below. Declare s1 as String s1; one time outside the loop. To end the loop, simply use ctrl+z.
while (sc.hasNext())
{
s1 = sc.next();
System.out.println(s1);
System.out.print("Enter your sentence: ");
}

Runtime Error Using Scanner class [duplicate]

I got an run time exception in my program while I am reading a file through a Scanner.
java.util.NoSuchElementException: No line found
at java.util.Scanner.nextLine(Unknown Source)
at Day1.ReadFile.read(ReadFile.java:49)
at Day1.ParseTree.main(ParseTree.java:17)
My code is:
while((str=sc.nextLine())!=null){
i=0;
if(str.equals("Locations"))
{
size=4;
t=3;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Professions"))
{
size=3;
t=2;
str=sc.nextLine();
str=sc.nextLine();
}
if(str.equals("Individuals"))
{
size=4;
t=4;
str=sc.nextLine();
str=sc.nextLine();
}
int j=0;
String loc[]=new String[size];
while(j<size){
beg=0;
end=str.indexOf(',');
if(end!=-1){
tmp=str.substring(beg, end);
beg=end+2;
}
if(end==-1)
{
tmp=str.substring(beg);
}
if(beg<str.length())
str=str.substring(beg);
loc[i]=tmp;
i++;
if(i==size ){
if(t==3)
{
location.add(loc);
}
if(t==2)
{
profession.add(loc);
}
if(t==4)
{
individual.add(loc);
}
i=0;
}
j++;
System.out.print("\n");
}
with Scanner you need to check if there is a next line with hasNextLine()
so the loop becomes
while(sc.hasNextLine()){
str=sc.nextLine();
//...
}
it's readers that return null on EOF
ofcourse in this piece of code this is dependent on whether the input is properly formatted
I also encounter with that problem.
In my case the problem was that i closed the scanner inside one of the funcs..
public class Main
{
public static void main(String[] args)
{
Scanner menu = new Scanner(System.in);
boolean exit = new Boolean(false);
while(!exit){
String choose = menu.nextLine();
Part1 t=new Part1()
t.start();
System.out.println("Noooooo Come back!!!"+choose);
}
menu.close();
}
}
public class Part1 extends Thread
{
public void run()
{
Scanner s = new Scanner(System.in);
String st = s.nextLine();
System.out.print("bllaaaaaaa\n"+st);
s.close();
}
}
The code above made the same exaption, the solution was to close the scanner only once at the main.
You're calling nextLine() and it's throwing an exception when there's no line, exactly as the javadoc describes. It will never return null
https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
For whatever reason, the Scanner class also issues this same exception if it encounters special characters it cannot read. Beyond using the hasNextLine() method before each call to nextLine(), make sure the correct encoding is passed to the Scanner constructor, e.g.:
Scanner scanner = new Scanner(new FileInputStream(filePath), "UTF-8");
Your real problem is that you are calling "sc.nextLine()" MORE TIMES than the number of lines.
For example, if you have only TEN input lines, then you can ONLY call "sc.nextLine()" TEN times.
Every time you call "sc.nextLine()", one input line will be consumed. If you call "sc.nextLine()" MORE TIMES than the number of lines, you will have an exception called
"java.util.NoSuchElementException: No line found".
If you have to call "sc.nextLine()" n times, then you have to have at least n lines.
Try to change your code to match the number of times you call "sc.nextLine()" with the number of lines, and I guarantee that your problem will be solved.
Need to use top comment but also pay attention to nextLine(). To eliminate this error only call
sc.nextLine()
Once from inside your while loop
while (sc.hasNextLine()) {sc.nextLine()...}
You are using while to look ahead only 1 line. Then using sc.nextLine() to read 2 lines ahead of the single line you asked the while loop to look ahead.
Also change the multiple IF statements to IF, ELSE to avoid reading more than one line also.
I ran into this problem, my structure was:
1 - System
2 - Registration <-> 3 - validate
I was closing Scanner on each of the 3 steps. I started to close the Scanner only in system and it solved.

hasNext() - when does it block and why?

I'm trying to read commands via a Scanner Object. For checking the Input Syntax I use sc.hasNext() (for the case of missing commands). It did work fine for many cases already, but now I have the case that's described in the JavaAPI as "MAY block and wait for Input".
When does the hasNext() method block and how can I control it? The funny Thing is that it work's perfectly fine with 3 cases before the block. Also the JavaAPI describes hasNext() as the proper method for checking wether there is another Input or not so that the Method next() doesn't produce an Exception.
Here is the code I did produce till now:
if (sc.hasNext() && sc.next().equals("create")) {
if (sc.hasNextInt()) {
width = sc.nextInt();
if (width > 0) {
if (sc.hasNextInt()) {
heigth = sc.nextInt();
if (heigth > 0) {
if (sc.hasNext()) { //At this point the hasNext Statement blocks for //no reason till an Input is made.
charset = sc.next();
Image = new AsciiImage(width, heigth,charset);
} else {
ret = false;
System.out.println("INPUT MISMATCH");
}
} ...//and so on
Thanks in advance, I couldn't find anything on this Topic an my own.
Edit: The Scanner is defined as a System.in, but that shouldn't be a Problem - at least it hasn't been one till now.
There is a difference between testing via Console or via TextFile. If I read from Console the program expects a Stream and it will wait for further Input.
When testing via Input from Textfile (still with System.in for the Scanner, using Java Program ) the hasNext() will return false at the end of the file as no further Input can be done.
I can't really find documentation (in https://docs.oracle.com/javase/9/docs/api/java/util/Scanner.html#hasNext--) on this Topic. So if anyone finds a proper and technical correct answer I would be very greatfull.
If you have nothing else to do while waiting for user input, then it's fine to be blocked at that call until the next input arrives.
If you do want to run other code while waiting for input, spawn a new thread and call hasNext and other blocking scanner methods from there.
I'm not sure , but the following is my own experience :
when the Scanner object is fed with a file , it will not be blocking !
By the term "fed with a file " I mean that the scanner is constructed like this : Scanner scanner = new Scanner("myFile.txt");
But if the scanner is constructed using the getInputStream()method of a Socket object , like this :
input = socket.getInputStream();
Scanner scanner = new Scanner(input);
the scanner will be blocking !

Categories