java - 写入 stdout,也像真正的终端一样打印提供的输入

标签 java linux shell io-redirection

让我们有一个简单的 Java 应用程序,其中我有以下代码来扫描用户输入:

Scaner scan = new Scanner(System.in);
System.out.print("Enter the value: ");
int value = scan.nextInt();
System.out.println("You entered: " + value); 

当我手动运行它时,正如预期的那样,我看到了我输入的内容,示例运行将是:

Enter the value: 3
You entered: 3

但是,当我有一个包含内容的文件时

3

我想通过这个将程序 stdout 重定向到一个文件:

java Test < INPUT > OUTPUT

我得到的全部在 cat OUTPUT 中:

Enter the value: You entered: 3

由于输入的值没有显示在标准输出上,这是正确的,它们不在标准输出上,我知道,我看到它们是因为我手动将它们输入到我的终端。但是,当我像那样重定向标准输出时,我怎样才能让它们也被看到呢?

编辑: 我可以看到代码正在生成 read(0,系统调用。

$ (strace -ff -e trace=read -e read 2>&1 java Test < INPUT) | grep "read(0,"
[pid  7297] read(0, "3\n", 8192)        = 2

有没有更好的拦截方式?

编辑 2: 我的意思是,当我使用 java < INPUT > OUTPUT 运行它时,输出应该如下所示

Enter the value: 3
You entered: 3

最佳答案

您无法修改提供的代码,但可以修改启动方式。

我提供的是假设 System.in 发生变化的 hack。我做了什么:

1) 我使用单个 main 方法和您发布的代码制作了一个测试程序。我启动了它:

$ java -cp dist/Test.jar test.Test <input 
Enter the value: You entered: 3

2) 我写了一个 java 程序来做

  1. 重定向输入流(System.in)
  2. 启动测试.Test.main

代码:

package redirecter;

import java.io.IOException;
import java.io.InputStream;

public class Redirecter {

    public static void main(String[] args) {
        final InputStream oldIn = System.in;
        InputStream hackedIn = new InputStream() {

            @Override
            public int read() throws IOException {
                int b = oldIn.read();
                System.out.write(b);
                return b;
            }

            @Override
            public int read(byte[] b, int off, int len) throws IOException {
                int res = oldIn.read(b, off, len);
                System.out.write(b, off, res);
                return res;
            }
        };
        System.setIn(hackedIn);

        test.Test.main(args);
    }
}

3) 我用新方法启动旧代码:

$ java -cp dist/Test.jar:../Redirecter/dist/Redirecter.jar redirecter.Redirecter <input 
Enter the value: 3
You entered: 3

提供的代码未经编辑;它只是通过棘手的方式推出的。所有参数和 jvm 选项都已保存。如果您有多个入口点,您可以使用反射而不是简单地调用 test.Test.main(args);

坏点:如果有人在提供的代码中编辑 System.in,黑客就会被破坏。但在使用标准输入之前它似乎是安全的。

关于java - 写入 stdout,也像真正的终端一样打印提供的输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20058909/

相关文章:

bash - 在两个变量 bash 中分割带有两个或单个字符串的行

shell - "xclip -sel"是什么意思?

java - 如何使用Scanner取出奇数行并按顺序排列?

java - 如果两个类都在同一个包中,子类可以访问父类私有(private)成员吗

linux - Linux 中应用程序的初始化

windows - 如何在 Windows 主机上编译针对 Linux x64 的交叉编译器?

java - 如何将通用的rest xml 文件读入java 对象?

java - 测试一个类而不使用另一个类

linux - 使用 netcat 和 grep 有条件地运行命令

java - 从 java 运行 shell 脚本