滚烫 java --- 使用来自 bash 的 java 处理标准输入时出现一些奇怪的行为

piping hot java --- some strange behavior when processing stdin with java from bash

假设我有以下(愚蠢的)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 中得到的答案与在 运行ning

中得到的答案不同
$ java Minimal

并(交互地)键入 y 后跟 <ENTER> --- 似乎等同于上面使用 printf 自动输入的内容。有什么想法吗?

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

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

为避免此问题,请不要为同一个 InputStream.

创建多个 Scanner 实例