在Java6中使用继承的stdin/stdout/stderr启动进程
如果我通过Java的类启动一个进程,我可以完全访问该进程的标准输入、标准输出和标准错误流,如Java在Java6中使用继承的stdin/stdout/stderr启动进程,java,io,process,pipe,Java,Io,Process,Pipe,如果我通过Java的类启动一个进程,我可以完全访问该进程的标准输入、标准输出和标准错误流,如JavaInputStreams和OutputStreams。但是,我无法找到一种方法将这些流无缝连接到System.in、System.out和System.err 可以使用redirectErrorStream()获取包含子流程的标准输出和标准错误的单个InputStream,然后循环并通过我的标准输出发送,但我找不到这样做的方法,让用户输入流程,如果我使用Csystem()调用,他或她可能会这样做
InputStreams
和OutputStreams
。但是,我无法找到一种方法将这些流无缝连接到System.in
、System.out
和System.err
可以使用redirectErrorStream()
获取包含子流程的标准输出和标准错误的单个InputStream
,然后循环并通过我的标准输出发送,但我找不到这样做的方法,让用户输入流程,如果我使用Csystem()
调用,他或她可能会这样做
这在JavaSE7中出现时似乎是可能的——我只是想知道现在是否有解决办法。如果子进程中的结果执行重定向,则可获得额外积分。您需要将输出、错误和输入流复制到系统版本。最简单的方法是使用Commons IO包中的类。这看起来正是你需要的。复制方法调用需要在单独的线程中进行
以下是基本代码:
// 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:
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();
}
对于
系统。在
中,使用以下pipein()
而不是pipe()
实施:
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();
}
太好了-我只是想知道如何做到这一点。是的,Stackoverflow:)不太好。copy将InputStream作为它的第一个参数,因此这不适用于getOutputStream。所以它是IOUtils.copy(process.getInputStream(),System.out);这有点让人困惑,因为getOutputStream实际上是通过管道传输到流程的输入端的。getInputStream()是应该通过管道传输到stdout的进程(是的,听起来倒过来)。因此,虽然这个结构看起来不错,但对IOUtils的调用看起来是错误的,现在让我有点困惑…错误。这只是在父级和子级的输入/输出流之间传输数据,不允许它继承它们。例如,即使Java命令是在终端上启动的(C isatty()==true或System.console()!=null),子级也不会认为自己正在终端中运行,因为其输入/输出流是管道。这一点很重要,因为某些(大多数)程序在终端中运行时表现不同。Java 7的ProcessBuilder.Redirect.INHERIT在这方面工作正常;好像不管用?
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();
}