Java 8 流过滤 CSV 中的行但保留第一行

Xtr*_*mer 3 java java-8 java-stream

我想从 CSV 文件中删除包含错误日期的行。在此过程中,CSV 文件应保留标题行。所有这些我想使用 java 8 流来执行。

起初我想到了这个:

try (Stream<String> linesUnfiltered = Files.lines(f.toPath(), StandardCharsets.UTF_8)) {
    Stream<String> firstLine = linesUnfiltered.limit(1);
    Stream<String> linesFiltered = linesUnfiltered
            .filter(e -> e.contains(sdfFileContent.format(fileDate)));
    Stream<String> result = Stream.concat(firstLine, linesFiltered);
    Files.write(f.toPath(), (Iterable<String>) result::iterator);
}
Run Code Online (Sandbox Code Playgroud)

但这会抛出异常,java.lang.IllegalStateException: stream has already been operated upon or closed因为linesUnfiltered被重用了。网上的建议是使用 a Supplier<Stream<String>>,但我的理解是供应商每次调用都会读取文件supplier.get(),效率不是很高。

这就是为什么我问是否有另一种方法比这更有效?我非常确定应该可以在同一个流上执行这两个操作......

编辑:

不是重复项,因为不应删除第一项。它应该只被排除在过滤过程之外,但仍然可以在结果流中使用

ern*_*t_k 6

您可以使用读取器并调用其readLine方法来使用标头,然后过滤结果lines()(在使用同一读取器的第一行之后):

try (BufferedReader reader = Files.newBufferedReader(f.toPath(), 
                                  StandardCharsets.UTF_8)) {

    Stream<String> firstLine = Stream.of(reader.readLine());
    Stream<String> linesFiltered = reader.lines()
            .filter(e -> e.contains(sdfFileContent.format(fileDate)));
    Stream<String> result = Stream.concat(firstLine, linesFiltered);

    ...
Run Code Online (Sandbox Code Playgroud)