将一个流映射到另一个流,并在第二个流关闭时关闭第一个流

时间:2016-01-24 15:33:56

标签: java eclipse resources java-8 java-stream

我有一个日志文件,我想用它来创建一个LogMessage对象。我想从文件中流式传输线条,并将每个线条映射到新的LogMessage。下面的代码有效,但Eclipse发出警告:

  

资源泄漏:' lineStream'从未关闭

public static Stream<LogMessage> streamSingleLineLogMessages(Path path) {
    try {
        Stream<String> lineStream = Files.lines(path, StandardCharsets.ISO_8859_1);
        Stream<LogMessage> logMessageStream =
                lineStream.map(message -> new LogMessage(path, message));
        logMessageStream.onClose(lineStream::close);
        return logMessageStream;
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

如果我添加一个finally块,并在那里关闭它,那么当方法返回时我会关闭流(我认为)。在任何情况下,它在我使用它时都会关闭。

那么确保内部流关闭的最佳方法是什么?或者代码可能是正确的,但Eclipse并没有意识到它?

1 个答案:

答案 0 :(得分:3)

你实际上不应该需要这些,而是​​:

public static Stream<LogMessage> streamSingleLineLogMessages(Path path) throws IOException {
    return Files.lines(path, StandardCharsets.ISO_8859_1)
                .map(message -> new LogMessage(path, message));
}

方法Files.lines(path, cs)返回一个Stream<Path>,它已经有一个关闭内部BufferedReader的关闭处理程序。当此Stream映射到Stream<LogMessage>时,将保留关闭处理程序。

这意味着对于新的Stream<LogMessage>,已经有一个关闭处理程序关闭BufferedReader,因此您无需自己添加它。

您只需要确保在使用此方法时,将其包装在try-with-resources构造中:

try (Stream<LogMessage> messageStream = streamSingleLineLogMessages(path)) {
    // do something with the stream
}