6

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.

skaffman
  • 398,947
  • 96
  • 818
  • 769
mPierce
  • 61
  • 1
  • 1
  • 2
  • 1
    Can you put some error checking prints in the two while loops and tell me which one it gets stuck in? – Lucas Mar 22 '12 at 05:35
  • I tried putting prints in each loop, but it doesn't seem to loop infinitely, instead its more like the outer while loop is waiting infinitely for more input – mPierce Mar 23 '12 at 06:46
  • someone figured that out below. – Lucas Mar 23 '12 at 16:08
  • 2
    possible duplicate of [How to terminate Scanner when input is complete?](http://stackoverflow.com/questions/16206813/how-to-terminate-scanner-when-input-is-complete) – Basilevs Sep 06 '14 at 15:07

5 Answers5

0

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");

}
Mirror318
  • 11,875
  • 14
  • 64
  • 106
  • This makes no sense. What is the point of a Boolean property that _always_ evaluates to true. Something isn't adding up. What am I missing? – Nate T Nov 10 '20 at 19:22
  • @NathanToulbert You're right, I wrote this answer 7 years ago and I was caught up following the asker's existing code. You'd only want the `hasNextLine` if you plan on terminating system input. – Mirror318 Nov 10 '20 at 20:55
0

How do you know when the user has finished with the inputs and the next "Enter" is supposed to not signify a new line of input, but the end of the inputs?
You can try counting the number of lines and breaking out of the loop after a maximum. Or you can look for a specific input like "submit" to break out of the loop. Otherwise, with scanner.hasNextLine(), the program considers every carriage return to be a new line, hence the condition never fails.

Senozoid
  • 11
  • 2
0

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");

    }
Shashank Kadne
  • 7,993
  • 6
  • 41
  • 54
0

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.

me_digvijay
  • 5,374
  • 9
  • 46
  • 83
  • 1
    But what would I store in the string variable? The program must read from the console, and if I save the line of input to a string, wont the program will still wait for a new line of input? – mPierce Mar 23 '12 at 06:45
0

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
Dunes
  • 37,291
  • 7
  • 81
  • 97