如何将Process的输入/输出流复制到系统对应的流程?

这是对这个问题的跟进。 答案表明存在

将Process out,err和输入流复制到System版本

使用IOUtils.copy如下(修复各种编译错误后):

 import org.apache.commons.io.IOUtils; import java.io.IOException; public class Test { public static void main(String[] args) throws IOException, InterruptedException { final Process process = Runtime.getRuntime().exec("/bin/sh -i"); new Thread(new Runnable() {public void run() { try { IOUtils.copy(process.getInputStream(), System.out); } catch (IOException e) {} } } ).start(); new Thread(new Runnable() {public void run() { try { IOUtils.copy(process.getErrorStream(), System.err); } catch (IOException e) {} } } ).start(); new Thread(new Runnable() {public void run() { try { IOUtils.copy(System.in, process.getOutputStream()); } catch (IOException e) {} } } ).start(); process.waitFor(); } } 

但是,生成的代码不适用于执行sh -i命令的交互式进程。 在后一种情况下,对任何sh命令都没有响应。

所以我的问题是:你能否建议一种替代方法来复制可用于交互式流程的流?

问题是IOUtil.copy()正在运行,而InputStream中有数据要复制。 由于您的进程只是不时生成数据,因此IOUtil.copy()退出,因为它认为没有要复制的数据。

只需手动复制数据并使用布尔值来停止外部的线程forms:

 byte[] buf = new byte[1024]; int len; while (threadRunning) { // threadRunning is a boolean set outside of your thread if((len = input.read(buf)) > 0){ output.write(buf, 0, len); } } 

这将读取块中与inputStream上可用的字节数一样多的字节,并将所有字节复制到输出。 内部InputStream将线程放入wait() ,然后在数据可用时唤醒它。
因此,在这种情况下,它可以像您一样高效。

Process.getOutputStream()返回一个BufferedOutputStream ,因此如果您希望输入实际到达子进程,则必须在每次write()之后调用flush() write()

您还可以重写您的示例以在一个线程上执行所有操作(尽管它使用轮询同时读取System.in和进程’stdout):

 import java.io.*; public class TestProcessIO { public static boolean isAlive(Process p) { try { p.exitValue(); return false; } catch (IllegalThreadStateException e) { return true; } } public static void main(String[] args) throws IOException { ProcessBuilder builder = new ProcessBuilder("bash", "-i"); builder.redirectErrorStream(true); // so we can ignore the error stream Process process = builder.start(); InputStream out = process.getInputStream(); OutputStream in = process.getOutputStream(); byte[] buffer = new byte[4000]; while (isAlive(process)) { int no = out.available(); if (no > 0) { int n = out.read(buffer, 0, Math.min(no, buffer.length)); System.out.println(new String(buffer, 0, n)); } int ni = System.in.available(); if (ni > 0) { int n = System.in.read(buffer, 0, Math.min(ni, buffer.length)); in.write(buffer, 0, n); in.flush(); } try { Thread.sleep(10); } catch (InterruptedException e) { } } System.out.println(process.exitValue()); } } 

您应该使用ProcessBuilder.redirectOutput方法和朋友。 在这里阅读更多