从 java.lang.Process 和 Java 8 CompletableFuture 同时读取 stdout/stderr?
Reading stdout/stderr simultaneously from java.lang.Process with Java 8 CompletableFuture?
假设我有一个 java.lang.Process process
对象代表我想从 Java 开始的子流程。我需要将子流程的 stdout
和 stderr
输出合并为一个 String
,为了这个问题的目的,我选择存储 stdout
首先,然后是 stderr
。根据我目前的理解,我应该同时阅读它们。我想 CompletableFuture
听起来是个不错的任务?
因此,我有以下代码片段:
获取输出
final CompletableFuture<String> output = fromStream(process.getInputStream()).thenCombine(
fromStream(process.getErrorStream()),
(stdout, stderr) -> Stream.concat(stdout, stderr).collect(Collectors.joining("\n")));
// to actually get the result, for example
System.out.println(output.get());
fromStream()
辅助方法
public static CompletableFuture<Stream<String>> fromStream(final InputStream stream) {
return CompletableFuture.supplyAsync(() -> {
return new BufferedReader(new InputStreamReader(stream)).lines();
});
}
是否有 better/nicer Java-8 方法来完成此任务?我知道 ProcessBuilder
中有 redirectOutput()
and redirectError()
方法,但我不认为我可以使用它们重定向到 String
?
正如评论中所指出的,我错过了 redirectErrorStream(boolean)
方法,该方法允许我在内部将 stderr
传输到 stdout
,因此只有一个流需要处理。在这种情况下,使用 CompletableFuture
完全是矫枉过正(双关语意想不到的......?)没有它我可能会更好。
假设我有一个 java.lang.Process process
对象代表我想从 Java 开始的子流程。我需要将子流程的 stdout
和 stderr
输出合并为一个 String
,为了这个问题的目的,我选择存储 stdout
首先,然后是 stderr
。根据我目前的理解,我应该同时阅读它们。我想 CompletableFuture
听起来是个不错的任务?
因此,我有以下代码片段:
获取输出
final CompletableFuture<String> output = fromStream(process.getInputStream()).thenCombine(
fromStream(process.getErrorStream()),
(stdout, stderr) -> Stream.concat(stdout, stderr).collect(Collectors.joining("\n")));
// to actually get the result, for example
System.out.println(output.get());
fromStream()
辅助方法
public static CompletableFuture<Stream<String>> fromStream(final InputStream stream) {
return CompletableFuture.supplyAsync(() -> {
return new BufferedReader(new InputStreamReader(stream)).lines();
});
}
是否有 better/nicer Java-8 方法来完成此任务?我知道 ProcessBuilder
中有 redirectOutput()
and redirectError()
方法,但我不认为我可以使用它们重定向到 String
?
正如评论中所指出的,我错过了 redirectErrorStream(boolean)
方法,该方法允许我在内部将 stderr
传输到 stdout
,因此只有一个流需要处理。在这种情况下,使用 CompletableFuture
完全是矫枉过正(双关语意想不到的......?)没有它我可能会更好。