如果我通过Java的ProcessBuilder类启动进程,则可以完全访问该进程的标准输入,标准输出和标准错误流,如Java InputStreams和OutputStreams。 但是,我找不到将这些流无缝连接到System.in,System.out和System.err的方法。
可以使用redirectErrorStream()来获取包含子流程的标准输出和标准错误的单个InputStream,然后循环遍历并通过我的标准输出将其发送出去,但是我找不到一种方法来让它 用户输入流程,就像我使用C system()调用时可以输入的那样。
Java SE 7发行时似乎有可能实现—我只是想知道现在是否有解决方法。 如果子进程中isatty()的结果进行了重定向,则奖励积分。
您将需要将Process输出,err和输入流复制到System版本。 最简单的方法是使用Commons IO包中的IOUtils类。 复制方法看起来就是您所需要的。 复制方法调用将需要在单独的线程中。
这是基本代码:
1 2 3 4 5 6 7 8 9 10 11
| // 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(); |
John答案的一种变体,可以编译,不需要您使用Commons IO:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| 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();
} |
对于System.in,请使用以下pipein()而不是pipe()
1
| pipein(System.in, p.getOutputStream()); |
实现方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| private static void pipein(final InputStream src, final OutputStream dest) {
new Thread(new Runnable() {
public void run() {
try {
int ret = -1;
while ((ret = System.in.read()) != -1) {
dest.write(ret);
dest.flush();
}
} catch (IOException e) { // just exit
}
}
}).start();
} |