扫描器在没有输入时冻结程序。

huangapple go评论71阅读模式
英文:

Scanner Freezes Program When No Input Is Given

问题

我正在制作一个主要与管道一起使用的应用程序。在程序开始时,这是我如何获取所有输入的方式:

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

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

scanner.close();

在与管道一起使用时,这个方法效果很好。例如,运行 ls | java -jar ... 会打印出从 ls 得到的所有行。然而,当我只运行 java -jar ...,没有输入/管道时,程序会冻结,什么也不会发生。即使我按下回车并不断敲击键盘,程序仍然卡住。我只能使用 ctrl-c 来停止程序。我认为这是因为没有内容可读,因此 Scanner 会等待直到有内容可读。如何在不冻结的情况下从 System.in 中读取所有行,或者是否有更好的方法来实现这一点?谢谢。

编辑:
将这个问题标记为重复的人显然没有阅读我的问题。我的问题是要检查 System.in 是否为空,以免冻结程序,而不是如何通过输入阶段。程序之所以冻结,是因为 System.in 中没有内容,所以 Scanner 会一直等待,但我希感知是否有内容在 System.in 中。

答案:
感谢 @QiuZhou 的答案。我修改了他的第二个示例,得到了这个代码:

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

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

它运行得非常好。


<details>
<summary>英文:</summary>

I&#39;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&#39;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.

</details>


# 答案1
**得分**: 4

因为你说了,"没有内容可读,所以扫描器会等待直到有内容可读",所以它会冻结。但是你想要"从System.in读取所有行而不冻结",这对我来说听起来有些矛盾,这不像从文件中读取,我们不知道使用你的程序的人会输入多少行,除非这个人告诉我们。我建议你定义一个特殊的字符作为`输入结束`的标志,例如`done`,当用户决定完成输入时,只需输入`done`以结束等待:

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

        System.out.println("请输入内容。输入'done'表示完成。");

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

        scanner.close();

要在不被卡住的情况下检查System.in中是否有内容可读,你可以使用BufferedReader.ready()来实现,正如文档所说,"请注意,只有在流上的下次读取不会阻塞时,in.ready()才会返回true。"

        System.out.println("请输入内容。输入'done'表示完成。");

        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);
            }
            //由于ready()不会阻塞,你可以在这里添加额外的逻辑,比如如果从输入中读取下一行需要太长时间,
            //你可以在这里直接结束循环
            // break;
        }
英文:

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&lt;String&gt; input = new ArrayList&lt;&gt;();

        System.out.println(&quot;Please enter something. Enter &#39;done&#39; when finished.&quot;);

        while (scanner.hasNextLine()) {
            String nextLine = scanner.nextLine();
            if(nextLine.equals(&quot;done&quot;))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(&quot;Please enter something. Enter &#39;done&#39; when finished.&quot;);

        List&lt;String&gt; input = new ArrayList&lt;&gt;();
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while(true) {
            if (reader.ready()) {
                String nextLine = reader.readLine();
                if(nextLine.equals(&quot;done&quot;))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;
        }

huangapple
  • 本文由 发表于 2020年10月15日 13:22:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/64365322.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定