使用 rJava 在 R 中显示 Java 控制台输出

Display Java console output in R using rJava

我创建了以下 Java class 并将其保存为 Test.java,然后在命令行上使用 javac Test.java 编译成 Test.class:

public class Test {

  public Test() {
  }

  public double power(double number) {
    System.out.println("calculating...");
    return number * number;
  }
}

此外,我创建了以下 R 脚本并将其保存为 test.R:

library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)

当我执行它时,例如在命令行上使用 R CMD BATCH test.R,我得到以下输出,这就是我想要的:

calculating...
[1] 9

但是,当我将此脚本包装在 Markdown 文档中并使用 knitr 对其进行编译时,我丢失了打印的有关正在进行计算的消息。例如,我将以下脚本保存在 test.Rmd 中并使用 RStudio 对其进行编译:

```{r echo=TRUE, warning=TRUE, results='show', message=TRUE}
library("rJava")
.jinit(classpath = getwd())
test <- .jnew("Test")
.jcall(test, "D", "power", 3)
```

这只有returns以下输出,没有消息:

## [1] 9

我在某处读到原因是 Java 中的 System.out.println 写入了 stdout,而这是否显示在 R 控制台中取决于解释器。例如,输出显示在 Unix 系统上,但不显示在 Windows 或 knitr.

我的问题:

  1. 以上解释正确吗?
  2. 如何在 R 中可靠地捕获或显示 System.out.println 的输出,而不考虑操作系统或解释器?
  3. 如果那不可能,那么设计有关 Java 中当前计算和进度的状态消息的更好方法是什么,以便 R 可以显示这些消息? 谢谢!

我会试着回答我自己的问题...看起来 RJava 的人实际上提供了一个内置的解决方案(感谢 Simon Urbanek,如果你读到这篇文章)。在 Java 代码的一侧,有 LGPL 许可的 JRI.jar,它与 rJava 一起交付(查看 jri 子目录中的 rJava package directory in your local R library path) 并且可以 copied/extracted 进入 Java 库路径。它只有 82kb,非常轻巧。

JRI 在 Java 中提供默认打印流的替换。本质上,您将系统输出重定向到 JRI 提供的 RConsoleOutputStream。我上面问题中的代码可以修改如下,以打印到 R 控制台而不是标准输出。

import java.io.PrintStream;
import org.rosuda.JRI.RConsoleOutputStream;
import org.rosuda.JRI.Rengine;

public class Test {

  public Test() {
    Rengine r = new Rengine();
    RConsoleOutputStream rs = new RConsoleOutputStream(r, 0);
    System.setOut(new PrintStream(rs));
  }

  public double power(double number) {
    System.out.println("calculating...");
    return number * number;
  }
}