【问题标题】:Scanner Freezes Program When No Input Is Given扫描仪在没有输入时冻结程序
【发布时间】:2020-10-15 05:22:25
【问题描述】:

我正在制作一个主要用于管道的应用程序。在程序开始时,我是这样获取所有输入的:

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

它就像一个魅力。

【问题讨论】:

  • @RichardBarker 抱歉我的问题措辞不好。我知道它为什么会冻结,只是不知道如何解决它。
  • 它不是“冻结”,它是等待你输入一些输入,它会继续处理输入,直到你按下 Ctrl+D 结束输入流
  • 您尝试过什么来调试“冻结”? 预期的行为是什么?
  • @NicoHaase 没有真正的例外行为,我知道它为什么不起作用。我想知道的是如何检测到 stdin 为空,或者程序在没有管道的情况下运行,因此扫描仪在查找下一行时不会卡住。

标签: java pipe


【解决方案1】:

冻结是因为,正如你所说,没有什么要读的,所以 Scanner 一直等到有要读的东西,但你想从 System.in 中读取所有行而不冻结,这听起来有点矛盾,这不像从文件中读取,我们不知道使用你的程序的人要输入多少行,除非有人告诉我们。我建议你定义一个特殊字符为end of input,例如done,当这个人确定他已经完成时,输入done结束等待:

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

要检查System.in 中是否有要阅读的内容而不会卡在那里,您可以使用BufferedReader.ready() 来执行此操作,正如文档所显示的那样,请注意,如果并且,in.ready() 将返回 true仅当流上的下一次读取不会阻塞时。

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

【讨论】:

  • 谢谢,我用 ready() 方法编辑了第二个。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-29
  • 2014-02-06
  • 2017-09-04
  • 1970-01-01
相关资源
最近更新 更多