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

Java 如何将流程的输入/输出流复制到其系统对应方?,java,process,io,stream,pipe,Java,Process,Io,Stream,Pipe,这是一个后续行动。答案表明有 将进程输出、错误和输入流复制到系统版本 使用IOUtils.copy如下(修复各种编译错误后): 但是,生成的代码不适用于交互式进程,例如执行sh-i命令的进程。在后一种情况下,对任何sh命令都没有响应 因此,我的问题是:您能推荐一种替代方法来复制将与交互进程一起工作的流吗?问题是,IOUtil.copy()正在运行,而InputStream中有数据要复制。由于您的进程只会不时生成数据,IOUtil.copy()会退出,因为它认为没有要复制的数据 只需手动复制数据并

这是一个后续行动。答案表明有

将进程输出、错误和输入流复制到系统版本

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

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


因此,我的问题是:您能推荐一种替代方法来复制将与交互进程一起工作的流吗?

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

只需手动复制数据并使用布尔值将线程形式停止在外部:

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将线程放入so
wait()
,然后在数据可用时将其唤醒。

因此,在这种情况下,它尽可能地高效。

进程。getOutputStream()
返回一个
BufferedOutputStream
,因此如果您想让输入真正到达子进程,您必须在每次
写入()之后调用
flush()

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


您应该改用
ProcessBuilder.redirectOutput
方法&friends。阅读更多内容

感谢您的建议。但是,
IOUtil.copy()
在到达流的末尾之前不会退出,因此它与您的代码没有太大区别,因为您的代码与
sh
有相同的问题。请看一下
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);
    }
}
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());
  }
}