在 Java 6 中使用继承的 stdin/stdout/stderr 启动进程

2022-09-01 14:38:52

如果我通过Java的ProcessBuilder类启动一个进程,我可以完全访问该进程的标准输入,标准输出和标准错误流,如Java和.但是,我找不到将这些流无缝连接到 、 和 的方法。InputStreamsOutputStreamsSystem.inSystem.outSystem.err

可以使用来获取包含子进程的标准输出和标准错误的单个,然后循环通过该子进程并通过我的标准发送它 - 但是我找不到一种方法来做到这一点并让用户键入到进程中,就像我使用C调用时他或她一样。redirectErrorStream()InputStreamsystem()

这在Java SE 7中似乎是可能的 - 我只是想知道现在是否有解决方法。如果子进程中的 isatty() 结果通过重定向进行,则奖励积分。


答案 1

您需要将流程流、错误流和输入流复制到系统版本。最简单的方法是使用 Commons IO 包中的 IOUtils 类。复制方法看起来是您需要的。复制方法调用需要位于单独的线程中。

以下是基本代码:

// Assume you already have a processBuilder all configured and ready to go
final Process process = processBuilder.start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getOutputStream(), System.out);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(process.getErrorStream(), System.err);
} } ).start();
new Thread(new Runnable() {public void run() {
  IOUtils.copy(System.in, process.getInputStream());
} } ).start();

答案 2

John答案的变体,编译并且不需要您使用Commons IO:

private static void pipeOutput(Process process) {
    pipe(process.getErrorStream(), System.err);
    pipe(process.getInputStream(), System.out);
}

private static void pipe(final InputStream src, final PrintStream dest) {
    new Thread(new Runnable() {
        public void run() {
            try {
                byte[] buffer = new byte[1024];
                for (int n = 0; n != -1; n = src.read(buffer)) {
                    dest.write(buffer, 0, n);
                }
            } catch (IOException e) { // just exit
            }
        }
    }).start();
}

推荐