4

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

背景故事:我正在尝试使用 processbuilder 启动一个可执行文件。(确切地说是源专用服务器/srcds.exe)

由于使用 processbuilder 启动它,这个可执行文件的控制台窗口仍然是空的。启动几秒钟后,可执行文件崩溃并显示错误“CTextConsoleWin32::GetLine: !GetNumberOfConsoleInputEvents”,因为它的控制台是空的。

4

3 回答 3

4

我认为您正在谈论使启动的进程'stdout 转到当前进程'stdout。如果您使用的是 JDK7,那很简单:

.redirectOutput(ProcessBuilder.Redirect.INHERIT)

更新:(评论太多)我认为你很困惑。当您从终端启动进程时,该进程将成为该终端进程的子进程,并将标准输出发送到该终端。当您从 Java 启动进程时,该进程是 Java 进程的子进程,其标准输出将发送到 Java。

在第一种情况下,有一个显示标准输出的终端,因为您自己从终端启动了它,这就是终端对标准输出所做的事情。然而,当从 Java 启动时,不会有终端窗口,除非您启动的进程中的某些东西打开了一个终端,并且您启动的进程的标准输出被交还给程序员,您可以随意处理。从终端启动时看到的等效行为是Redirect.INHERIT我已经提到的。

你现在的问题不是Java。您的问题是不了解此“srcds.exe”如何处理标准输入和标准输出。弄清楚这一点,然后回来询问如何使用 Java 做到这一点。

我现在只是在猜测,但您可以尝试从进程的标准输出中读取并将其反馈回标准输入。也许这就是它所期待的?不过,这听起来很疯狂。

于 2012-05-28T23:42:18.723 回答
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*
}
于 2012-05-28T22:44:30.647 回答
0

我已经为此苦苦挣扎了一段时间,但我想你可以做的最简单的方法是自己传输流,使用某种 StreamTransfer 类,你可以说哪个在单独的线程中InputStream写入哪个OutputStream以避免死锁。在此示例中,我执行lsthencat并手动将stdoutofls连接到stdinof cat,然后cat's stdouttoSystem.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()返回进程,您仍然可以检索所需的流并相应地传输。

于 2020-06-10T16:23:00.723 回答