java - Spark 数据集显示:无法多次捕获输出
问题描述
即使我已经解决了问题(请参阅答案),我仍在问这个问题,以挽救其他人同样的痛苦。
我需要一种方法来向我的 log4j 记录器显示我的数据集。我这样做是使用:
void org.apache.spark.sql.Dataset.show(int numRows, boolean truncate)
它只是记录到stdOut。为了捕获stdOut,我做了以下事情(在stackoverflow的其他地方找到了灵感):
void myMethod(Dataset<Row> data){
// Save the old System.out
PrintStream originalPrintStream = System.out;
// Tell Java to use your special stream
ByteArrayOutputStream logCollection = new ByteArrayOutputStream();
PrintStream printStreamForCollectingLogs = new PrintStream(logCollection);
System.setOut(printStreamForCollectingLogs);
// Print some output: goes to your special stream
data.show(MAX_DISPLAY_ROWS, false);
// Put things back
System.out.flush();
System.setOut(originalPrintStream);
logger.info("\n"+logCollection.toString());
logCollection.reset();
}
这仅有效一次,对同一数据集的同一方法的后续调用将无法捕获任何内容。我在用:
<groupId>org.apache.spark</groupId>
<artifactId>spark-sql_2.11</artifactId>
<version>2.4.5</version>
解决方案
这个问题似乎是由于数据集保留了它首先遇到的作为 stdOut 的字节流,因为我能够通过将我的替代 stdOut 流提取为类变量来解决这个问题:
private static ByteArrayOutputStream logCollection = new ByteArrayOutputStream();
private static PrintStream printStreamForCollectingLogs = new PrintStream(logCollection);
这意味着我logger.info("\n"+logCollection.toString())
每次都使用相同的字节流。这使我可以根据需要随时调用 myMethod 并每次都捕获输出。
推荐阅读
- angular - 延迟加载而不为模块添加路由段
- android - 添加新基准模块时同步失败
- ios - Xcode:iOS 应用程序突然总是在启动时崩溃
- python - python:解释如果列表:
- javascript - Opentok web 移动到 PC 方向
- c# - 迁移到 Asp.net core 3 改变了控制器响应?
- message-queue - ZeroMQ 消息队列
- laravel - 如何在当前用户中实现 setEagerLoads - Laravel
- c - C函数将函数作为参数传递,如何使用node-ffi包装这个函数?
- python-3.x - 如何从数据框中写入具有不同列名的excel?