'Java Scanner won't "finish" reading input

I've been having trouble using java's Scanner class. I can get it to read my input just fine, but the problem is when I want to output something. Given multiple lines of input, I want to print just ONE line when all the input has been read completely. Here's the code I use for reading input:

    public static void main(String[] args){
    Scanner scanner = new Scanner(System.in);   //scanner reads block of input
    while(scanner.hasNextLine()){    
        //body of loop goes here
        String s = scanner.nextLine();
        Scanner ls = new Scanner(s);   //scanner to parse a line of input
        while(ls.hasNext()){
        //body of nested loop goes here
        ls.next();
        }
    }
    System.out.println("Fin");
    }

Even when all lines of input have been read, the program doesn't reach the System.out.println message. (Note that the message can't go anywhere else or it will output as many times as the loop is run). How do I fix this? Any help would be greatly appreciated.



Solution 1:[1]

As I can see in your outer while loop you have used

scanner.hasNextLine();

method. This method gets blocked if it has to wait for the input. Also you have

Scanner scanner = new Scanner(System.in);

statement. So the system.in will be waiting for input all the time, hence the hasNextLine() method has to wait for the input. That is why the control gets stuck in the loop and can't proceed further.

To fix it you can first store input in a string variable and the call the scanner constructor on it.

Solution 2:[2]

You are reading from an Infinite stream in this case. hasNextLine() will keep returning true if there is another line in the input of this scanner. As its a System.in, it will keep reading from the Keyboard, unless you terminate it or tell the stream to stop.

Press "ctrl+Z" in the end, you will see that it works.

Edit : You could do something like this...

Scanner scanner = new Scanner(System.in);   //scanner reads block of input
        int BLOCK_SIZE  =3,count=1;
        while(scanner.hasNextLine()){    
            //body of loop goes here
            String s = scanner.nextLine();
            Scanner ls = new Scanner(s);   //scanner to parse a line of input
            while(ls.hasNext()){
            //body of nested loop goes here
            ls.next();
            }
            if(count++==BLOCK_SIZE)
            {
                break;
            }
        }
        System.out.println("Fin");

    }

Solution 3:[3]

You need to tell the program that there is going to be no more input. This is done by appending an EOF character. This can be done manually on Linux by pressing Ctrl-D in the console. I think on Windows you can press Ctrl-Z. The stream will be automatically closed if you are piping input from one program to another.

eg.

cat filename | java MyJavaProgram

Solution 4:[4]

The magic of

Scanner scanner = new Scanner(System.in);
    while(scanner.hasNextLine()){ 

Is that there will never stop being input from System (unless you close the input with ctrl+d (for macs)).

To stop the loop, I suggest throw something more in the condition than just hasNextLine().

E.g.

Scanner scanner = new Scanner(System.in);   //scanner reads block of input
    int BLOCK_SIZE  =3,count=1;
    while(scanner.hasNextLine() && count++ <= BLOCK_SIZE){   //<- Use count here.
        //body of loop goes here
        String s = scanner.nextLine();
        Scanner ls = new Scanner(s);   //scanner to parse a line of input
        while(ls.hasNext()){
        //body of nested loop goes here
        ls.next();
        }
    }
    System.out.println("Fin");

}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 me_digvijay
Solution 2
Solution 3 Dunes
Solution 4 Mirror318