首页 > 解决方案 > 在线程上解析标准输出

问题描述

我想启动一个新线程来处理标准输出,并检查每一行是否包含 String Success!。这就是我所拥有的:

final Thread ioThread = new Thread(() -> {
    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.out));
        String line;
        while ((line = reader.readLine()) != null) {
            if (line.contains("Success!")) {
                // FOUND LINE!!
            }
        }
        reader.close();
    } catch (final Exception e) {
        e.printStackTrace();
    }
});
ioThread.start();

问题是InputStreamReader构造函数需要一个InputStream,而不是一个PrintStream。我怎样才能解决这个问题?

标签: javastdout

解决方案


我认为如果您更详细地描述您需要实现的目标会更好,因为可能有更简单的方法来处理这个问题。

但是,可以通过调用来扫描您的进程自己的标准输出System.setOut(newOut),用合适的间谍流替换默认输出。

此调用使用连接到的 a 进行spy()调整,以在后台线程中执行扫描,该线程还将输出发送回 real :System.outPipedOutputStreamPipedInputStreamSystem.out

private static void spy() throws IOException {
    PipedOutputStream out = new PipedOutputStream();
    PipedInputStream in = new PipedInputStream(out);

    PrintStream sOut = System.out;

    System.setOut(new PrintStream(out));
    final Thread ioThread = new Thread(() -> {
        try(BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
            String line;
            while ((line = reader.readLine()) != null) {

                // Send line to real System.out:
                sOut.println(line);

                if (line.contains("Success!")) {
                    // FOUND LINE!!
                    System.err.println("=== Found a match: "+line);
                }
            }
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    });
    ioThread.start();
}

这个测试程序展示了它是如何工作的。

public static void main(String[] args) throws IOException {
    spy();

    String s = """
            one
            two
            three Success!
            four
            """;

    System.out.println(s);
    System.out.close();
}

印刷:

one
two
three Success!
=== Found a match: three Success!
four

请注意,有一个缺点是您的主程序必须关闭System.out,否则间谍线程不知道主应用程序何时完成编写 - 否则您将需要java.io.IOException: Write end dead在管道中进行处理。


推荐阅读