0

Obviously, my real code is more complex, but here's an example:

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in).useDelimiter("\n");
        String[] cmdSplit = null; 
        while (true) {
            while (input.hasNext()) {
                cmdSplit = input.next().split("\\s+");
                System.out.println("stuff");
            }
            for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
        }
    }
}

In the above example, the code takes input from System.in, splits it, and should output each piece. However, for some reason, the code after the inner while loop never executes. If I replace while with if, it works. If you test it, you can see it doesn't run infinitely, because it only prints "stuff" once, showing the loop runs once. What is the issue with the while loop?

3 Answers 3

3

Reading from System.in is different than reading from a file or other fixed-size source of input. The input doesn't necessarily exist until you create it, and so attempts to read it need to block until the input actually arrives (i.e. you type it). Try typing another line - you'll see the stuff message again; that will allow .hasNext() to return because there is now input.

To have .hasNext() return false the input source needs to be closed. For a command line application you can do this by sending the EOF signal (Ctrl+D on Linux) which tells the process stdin has no more input. That's not generally how you want a program to work, though, so if your intent is to only read one line and then move on, you should in fact be using an if instead of a while as you've tried to do. Later if you need to read more input you'll call .hasNext() again and your program will block there until the user passes more input.


As @user7 mentions your outer while (true) combined with while(input.hasNext()) is redundant. If you want to read only once get rid of the while (true) and use if (input.hasNext()). Otherwise if you want to read forever just combine the two loops:

while (input.hasNext()) {
  cmdSplit = input.next().split("\\s+");
  System.out.println("stuff");
  for (int i = 0; i < cmdSplit.length; i++) System.out.println(cmdSplit[i]);
} // Loop will terminate once stdin is closed, e.g. by the user sending EOF.
Sign up to request clarification or add additional context in comments.

4 Comments

Want to add a point here - there is no use in having the outer infinite loop as input.hasNext() is not going to return true thereafter (here it'll keep printing what it saw the last time)
Is there any way to detect the end without sending EOF?
There isn't an end before EOF is sent :) Until EOF is sent the program can continue reading input from the user indefinitely. Instead you generally want to read the input you expect and then stop doing so once you've read enough. It's common for interactive programs to add an "escape" of some sort, such as breaking out of the loop if the input string is empty. The exact behavior you'll want depends on your specific use case.
I'll probably use if and splits or something. I was trying to read to the end of user input, but I guess it makes sense why you can't until they say it is over.
-1

Yes , your code won't go to the for loop because the Scanner.hasNext() will always listen to the console for inputs.

You have to break the loop in order to come out and go to the for loop.

   Scanner input = new Scanner(System.in).useDelimiter("\n");
    String[] cmdSplit = null;
    while (true) {
      while (input.hasNext()) {
        cmdSplit = input.next().split("\\s+");
        System.out.println("stuff");
        break;
      }
      for (String element : cmdSplit) {
        System.out.println(element);
      }
    }

1 Comment

If your intent is to simply break after one pass through a while loop (as in while (...) { ...; break; } you could just use an if instead (if (...) { ...; }).
-1

The reason it is printing "stuff" only one time is because the hasNext() returned false.

Let me explain what I have observed.

To get "stuff" printed indefinately the assignment has to be removed. meaning once you assigned the input the scanner does not have any more token

The java.util.Scanner.hasNext() method Returns true if this scanner has another token in its input.

This will print indefinitely

 while (input.hasNext()) {
            // cmdSplit = input.next().split("\\s+");
            System.out.println("stuff");
        }

2 Comments

How can it print indefinitely when you have a break
Yea that is the right. did not saw it. Actually I Copied it from the wrong source. I am editing it now

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.