Scanner Freezes Program When No Input Is Given

Viewed 198

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.

1 Answers

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;
        }
Related