有没有办法在一个Java8流中读取两个或多个文件?

我喜欢新的Java8 StreamAPI,并且不仅要将它用于一个文件。 通常,我使用此代码:

Stream lines = Files.lines(Paths.get("/somepathtofile")); 

但如果可能的话,如何在一个流中读取两个文件?

没有任何额外的辅助函数或外部库,最简单的是:

 Stream lines1 = Files.lines(Paths.get("/somepathtofile")); Stream lines2 = Files.lines(Paths.get("/somepathtoanotherfile")); Stream.concat(lines1, lines) .filter(...) .forEach(...); 

如果没有声明Files.lines抛出一个已检查的exception,那么你就能做到

 Stream.of("/file1", "/file2") .map(Paths::get) .flatMap(Files::lines).... 

但是,唉,我们做不到。 有几种解决方法。 一种是创建自己的Files.lines版本,调用标准版本,捕获IOException并重新呈现为UncheckedIOException 。 另一种方法是使用抛出已检查exception的方法生成函数的更通用方法。 它看起来像这样:

 @FunctionalInterface public interface ThrowingFunction extends Function { @Override public default R apply(T t) { try { return throwingApply(t); } catch (Exception e) { throw new RuntimeException(e); } } public static Function wrap(ThrowingFunction f) { return f; } R throwingApply(T t) throws Exception; } 

接着

 Stream.of("/somefile", "/someotherfile", "/yetanotherfile") .map(Paths::get) .flatMap(ThrowingFunction.wrap(Files::lines)) ..... 

有几个库经历了为每个function界面编写类似上面的东西的麻烦。

使用cyclops-streams (我们创建的库),您可以编写

  SequenceM.of("/somepathtofile1","/somepathtofile2") .flatMapFile(File::new) .forEach(System.out::println); 

Javadoc SequenceM扩展了java.util.stream.Stream(以及org.jooq.lambda.Seq)以添加许多其他便利方法。

您可以使用以下代码

 Files.list(Paths.get("path")) .filter(Files::isRegularFile) .flatMap(s -> { try { return Files.lines(s); } catch (IOException e) { e.printStackTrace(); } return null; }) .forEach(System.out::println);