是否可以将输出流重定向回进程,或者根本不重定向?
背景故事:我正试图使用processbuilder启动一个可执行文件。准确的说是源码专用服务器srcds.exe)。
由于用processbuilder启动它,这个可执行文件的控制台窗口仍然是空的。在启动几秒钟后,该可执行文件就以 "CTextConsoleWin32::GetLine:!!GetNumberOfConsoleInputEvents "的错误信息崩溃,因为它的控制台是空的。
我想你说的是让启动的进程的stdout转到当前进程的stdout。如果你使用的是JDK7,那就很简单了。
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
更新 (太多评论) 我想你搞混了. 当你从一个终端启动一个进程时,这个进程就会成为该终端进程的一个子进程,并将stdout发送到该终端。当你从Java启动一个进程时,那么这个进程就是Java进程的一个子进程,它的stdout被发送到Java。
在第一种情况下,有一个终端显示stdout,因为你自己是从终端启动的,这就是终端对stdout的处理。然而,当从Java启动时,除非你启动的进程中的某个东西打开了一个终端窗口,否则就不会有终端窗口,而你启动的进程的stdout会交还给你这个程序员,让你随意处理。与你从终端启动时看到的行为相当的就是 Redirect.INHERIT
我已经提到过了。
你现在的问题不是Java。您的问题是不明白这个 "srcds.exe "期望如何处理 stdin 和 stdout。弄清楚这一点,然后再来问如何用 Java 来处理。
我现在只是猜测,但你可以尝试从进程的stdout中读取并将其反馈到stdin中。也许这就是它所期望的?不过这听起来很疯狂。
你可以得到这样的输出
ProcessBuilder pb = new ProcessBuilder(args);
Process p = pb.start();
//below code gets the output from the process
InputStream in = p.getInputStream();
BufferedInputStream buf = new BufferedInputStream(in);
InputStreamReader inread = new InputStreamReader(buf);
BufferedReader bufferedreader = new BufferedReader(inread);
String line;
while ((line = bufferedreader.readLine()) != null) {
*do something / collect output*
}
我一直在纠结这个问题,但最简单的我想你可以通过自己传输流,使用某种StreamTransfer类,你可以说是哪个 InputStream
被写到哪个 OutputStream
在不同的线程中执行,以避免死锁。在这个例子中,我在不同的线程中执行 ls
然后 cat
并手动接线 stdout
的 ls
进入 stdin
的 cat
,然后 cat
's stdout
到 System.out
来打印最终结果。
public class TestRedirectingStreams {
public static void main(String[] args) throws IOException, InterruptedException {
ExecutorService threads = Executors.newFixedThreadPool(10);
Process echo = Runtime.getRuntime().exec("ls"),
cat = Runtime.getRuntime().exec("cat");
threads.submit(StreamTransfer.transfer(echo.getInputStream(), cat.getOutputStream()));
threads.submit(StreamTransfer.transfer(cat.getInputStream(), System.out));
threads.shutdown();
}
}
class StreamTransfer implements Callable<Void> {
public static final int BUFFER_SIZE = 1024;
private InputStream in;
private OutputStream out;
public static StreamTransfer transfer(InputStream in, OutputStream out) {
return new StreamTransfer(in, out);
}
private StreamTransfer(InputStream in, OutputStream out) {
this.in = in;
this.out = out;
}
@Override
public Void call() throws Exception { // write to streams when thread executes
byte[] buffer = new byte[BUFFER_SIZE];
int read = 0;
while ((read = in.read(buffer)) != -1)
out.write(buffer, 0, read);
in.close();
out.close();
return null;
}
}
如果你想用ProcessBuilder来代替这个例子,那么这个例子就会保持不变,因为 ProcessBuilder.start()
返回的过程中,你仍然可以检索所需的流,并相应地传输。