java 子进程输出流_运行子进程,在Java中正确地提供输入和输出

您需要复制子进程的流和系统流(System.in,System.out和System.err)之间的输入和输出.这与

my recent quesion有关.到目前为止,我找到的最佳解决方案是:

import java.io.FileInputStream;

import java.io.FilterInputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.lang.reflect.Field;

import java.nio.ByteBuffer;

import java.nio.channels.AsynchronousCloseException;

import java.nio.channels.FileChannel;

class StreamCopier implements Runnable {

private InputStream in;

private OutputStream out;

public StreamCopier(InputStream in,OutputStream out) {

this.in = in;

this.out = out;

}

public void run() {

try {

int n;

byte[] buffer = new byte[4096];

while ((n = in.read(buffer)) != -1) {

out.write(buffer,n);

out.flush();

}

}

catch (IOException e) {

System.out.println(e);

}

}

}

class InputCopier implements Runnable {

private FileChannel in;

private OutputStream out;

public InputCopier(FileChannel in,OutputStream out) {

this.in = in;

this.out = out;

}

public void run() {

try {

int n;

ByteBuffer buffer = ByteBuffer.allocate(4096);

while ((n = in.read(buffer)) != -1) {

out.write(buffer.array(),n);

out.flush();

}

out.close();

}

catch (AsynchronousCloseException e) {}

catch (IOException e) {

System.out.println(e);

}

}

}

public class Test {

private static FileChannel getChannel(InputStream in)

throws NoSuchFieldException,IllegalAccessException {

Field f = FilterInputStream.class.getDeclaredField("in");

f.setAccessible(true);

while (in instanceof FilterInputStream)

in = (InputStream)f.get((FilterInputStream)in);

return ((FileInputStream)in).getChannel();

}

public static void main(String[] args)

throws IOException,InterruptedException,NoSuchFieldException,IllegalAccessException {

Process process = Runtime.getRuntime().exec("sh -i +m");

Thread outThread = new Thread(new StreamCopier(

process.getInputStream(),System.out));

outThread.start();

Thread errThread = new Thread(new StreamCopier(

process.getErrorStream(),System.err));

errThread.start();

Thread inThread = new Thread(new InputCopier(

getChannel(System.in),process.getOutputStream()));

inThread.start();

process.waitFor();

System.in.close();

outThread.join();

errThread.join();

inThread.join();

}

}

这里棘手的部分是从System.in中提取一个通道.如果没有这个,你将无法在子进程终止时中断读取输入的线程.

这种方法有一个严重的缺点:关闭System.in之后,你再也无法读取它了.我目前使用的解决方法是使用单个输入重定向线程用于所有子进程.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值