阅读 System.Out

Reading System.Out

所以,我想做的基本上是过滤通过 System.outSystem.err 的所有内容,是否可以应用某种过滤器或创建我自己的 OutputStreamSystem.out导流,然后正常处理?

为清楚起见编辑: 为了澄清,我需要从其他程序中读取 System.out 的内容,并按照我认为合适的方式对其进行操作,因此记录器并不是一个真正的选择,因为我无法控制其他程序将使用的内容。

为更清晰起见进行编辑: 我正在为一个更大的程序创建一个插件,该程序需要从其他插件读取写入 System.out 的所有内容。因为它是一个基于插件的系统,所以我的插件 运行 开启的进程将始终与其他插件 运行 开启的进程相同。

你应该使用记录器,但如果你不想,你可以创建自己的 PrintStream 来保存 System.out。然后调用 System.setOut(yourPrintStream).

有一点我不太清楚:你提到你想要 "read what goes out of System.out from other programs"。您的应用程序是在创建流程并希望监控其标准 out/err,还是您希望监控流程本身的标准 out/err?

对于前一种情况,创建进程后,您可以获得它的output, input and error流。

对于后一种情况,您可以将 Java 过程中的标准替换为 System.setOut(yourOwnOutputStream);

但是,如果您正在尝试处理完全不相关的流程流,我相信如果调用者不通过管道将 stdout/stderr 传递给您的流程(除非通过某些特定于平台的方法),就无法做到这一点


更新:

为了"intercept"标准出来的,跟那些经典"filter outputstreams"无异。你可以做的是这样的:

class AnalyzingOutputStream extends FilterOutputStream {

    public AnalyzingOutputStream (OutputStream out) {
        super(out);
    }

    @Override
    public void write(int b) {
          // do whatever analysis you want
          super.write(b);  // delegate to super class' write, which will 
                           // delegate to the filtered outputstream
    }
    // other overrides
}

为了使用它,您的主要逻辑应该做如下事情:

AnalyzingOutputStream analyzingOutputStream = new AnalyzingOutputStream(System.out);
System.setOut(analyzingOutputStream );

// then you can call your methods of AnalyzingOutputStream to do whatever you want

要捕获 Java 中另一个进程的所有输出,最简单的方法是使用 Runtime.exec 自己启动进程,这将为您提供一个 Process 对象,该对象具有 getOutputStream.读取该流将为您提供已启动进程的标准输出。

如果您正在尝试捕获任意进程的输出,您将面临更大的任务 - 这可能不是一个好主意。我不知道它在 Windows 上是如何工作的。在 Linux 下,您需要 运行 与您要调查的进程或(更有可能)root 处于同一用户下。您可以在 /proc/<process id>/fd/<file descriptor> 下查看任何给定进程的文件描述符。 stdin、stdout 和 stderr 的文件描述符分别为 0、1 和 2。我会建议你在这一点上停下来,重新考虑你要做什么。