3

I'm making an application that is mainly used with pipes. At the start of the program, here is how I get all my input:

Scanner scanner = new Scanner(System.in);
List<String> input = new ArrayList<>();

while (scanner.hasNextLine()) {
    input.add(scanner.nextLine());
}

scanner.close();

When used with pipes, this works well. For example, running ls | java -jar ... it prints out all the lines given from ls. However, when I just run java -jar ... with no input/pipe, it freezes and nothing happens. Even when I press enter and mash my keyboard it's still stuck. I can only stop the program by using ctrl-c. I think this is because there is nothing to read so Scanner waits until there is something to read. How do I read all lines from System.in without freezing, or is there a better way to do this? Thanks.

Edit: Whoever marked this as a duplicate clearly did not read my question. My question was to check if the System.in was empty to not freeze the program, not how to get past the input stage. It is freezing because there is nothing in System.in so Scanner is taking forever, but I want to check if there is nothing in System.in.

Answer: Thank you @QiuZhou for the answer. I modified his second example to get this:

List<String> input = new ArrayList<>();
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

while (reader.ready()) {
    String nextLine = reader.readLine();
    input.add(nextLine);
}

and it works like a charm.

Higigig
  • 1,175
  • 1
  • 13
  • 25
  • @RichardBarker Sorry for the bad wording in my question. I know why it's freezing, I just don't know how to fix it. – Higigig Oct 15 '20 at 05:30
  • 2
    It is not "freezing", it is *waiting* for you to type some input, and it'll keep processing input until you end the input stream by pressing Ctrl+D – Andreas Oct 15 '20 at 05:44
  • What have you tried to debug that "freezing"? What is the **expected** behaviour? – Nico Haase Oct 15 '20 at 07:04
  • @NicoHaase There isn't really an excepted behavior, I know why it isn't working. What I want to know is how I can detect that stdin is empty, or the program was run without a pipe, so the scanner doesn't get stuck while looking for the next line. – Higigig Oct 15 '20 at 07:06

1 Answers1

4

It's freezing because, as you said, there is nothing to read so Scanner waits until there is something to read, but you want to read all lines from System.in without freezing, it sounds kind of conflicting to me, it's not like reading from a file, we don't know how many lines whoever using your program is going to type in, unless the person tell us. I suggest you define a special character as end of input, for example, done, when the person decides he has finished, just enter done to end waiting:

        Scanner scanner = new Scanner(System.in);
        List<String> input = new ArrayList<>();

        System.out.println("Please enter something. Enter 'done' when finished.");

        while (scanner.hasNextLine()) {
            String nextLine = scanner.nextLine();
            if(nextLine.equals("done"))break;
            input.add(nextLine);
        }

        scanner.close();

To check if there is something to read in System.in without being stuck there, you can do it by using BufferedReader.ready(), as the document reads, Note that in.ready() will return true if and only if the next read on the stream will not block.

        System.out.println("Please enter something. Enter 'done' when finished.");

        List<String> input = new ArrayList<>();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            if (reader.ready()) {
                String nextLine = reader.readLine();
                if(nextLine.equals("done"))break;
                input.add(nextLine);
            }
            //since ready() will not block, you can add additional logic here, like if it
            //takes too long to read next line from input, you can just end here
            // break;
        }
Qiu Zhou
  • 1,235
  • 8
  • 12