【问题标题】:piping hot java --- some strange behavior when processing stdin with java from bash热腾腾的 java --- 使用 bash 中的 java 处理标准输入时的一些奇怪行为
【发布时间】:2019-11-17 05:24:58
【问题描述】:

假设我有以下(愚蠢的)java 程序,它在mainaux 之间来回循环,只要键入y

import java.util.Scanner;

public class Minimal {

    public static void main(String[] args) {

        System.out.println("in main...");

        Scanner scanner = new Scanner(System.in);

        String s;
        while(scanner.hasNextLine()) {

            s = scanner.nextLine();
            System.out.println(s);
            if(s.equals("y")) {
                aux();
                System.out.println("in main...");
            }       
        }
    }

    public static void aux() {

        System.out.println("in aux...");

        Scanner scanner = new Scanner(System.in);

        String s;
        while(scanner.hasNextLine()) {

            s = scanner.nextLine();
            System.out.println(s);
            if(s.equals("y")) {
                return;
            }
        }
    }
}

但是,当我跑步时

$ javac Minimal.java
$ printf "y\ny\ny\ny\ny\ny\ny\n" | java Minimal

在 bash 中,我得到的答案与运行时不同

$ java Minimal

然后输入(交互式)y,然后输入<ENTER> --- 似乎等同于上面自动输入的printf。有什么想法吗?

【问题讨论】:

  • aux返回后,您永远不会打印in main...
  • 它与“从标准输入读取的不同方式”无关,与您的输入有关。 Java 无法使用管道标准输入来区分来自用户的输入或来自另一个进程的输入。那是标准输入的“标准化”部分。
  • 谢谢---所以问题是为什么y后跟<ENTER>的序列不同于printf "y\ny\ny\ny\ny\ny..."
  • 现在编辑您的问题并解释如何它是不同的。带有实际输出的屏幕截图或示例会话会有所帮助。

标签: java bash java.util.scanner stdin


【解决方案1】:

区别在于缓冲。 Scanner 缓冲其输入,因此它可能一次消耗来自System.in 的多行。当您使用printf 时,数据立即可用,因此全部由main() 中的Scanner 实例使用。因此,在每次调用 aux() 时创建的 Scanner 没有更多数据可供读取。

当您以交互方式运行程序时,终端会在您输入数据时逐行发送数据,因此在每次读取时没有任何额外的数据可用于缓冲。

为避免此问题,请勿为同一个InputStream 创建多个Scanner 实例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-12
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多