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

vit*_*aut 7 java io pipe process stream

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

将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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Pet*_*ego 5

问题是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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