不需要重定向StdOut的过程必达。

问题描述 投票:4回答:3

是否可以将输出流重定向回进程,或者根本不重定向?

背景故事:我正试图使用processbuilder启动一个可执行文件。准确的说是源码专用服务器srcds.exe)。

由于用processbuilder启动它,这个可执行文件的控制台窗口仍然是空的。在启动几秒钟后,该可执行文件就以 "CTextConsoleWin32::GetLine:!!GetNumberOfConsoleInputEvents "的错误信息崩溃,因为它的控制台是空的。

java stdout processbuilder
3个回答
4
投票

我想你说的是让启动的进程的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中。也许这就是它所期望的?不过这听起来很疯狂。


0
投票

你可以得到这样的输出

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*
}

0
投票

我一直在纠结这个问题,但最简单的我想你可以通过自己传输流,使用某种StreamTransfer类,你可以说是哪个 InputStream 被写到哪个 OutputStream 在不同的线程中执行,以避免死锁。在这个例子中,我在不同的线程中执行 ls 然后 cat 并手动接线 stdoutls 进入 stdincat,然后 cat's stdoutSystem.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() 返回的过程中,你仍然可以检索所需的流,并相应地传输。

© www.soinside.com 2019 - 2024. All rights reserved.