有一种方法可以使用标准 Java 8 Stream API 将文件内容分区并处理为 n-size 块。您可以使用Collectors.groupingBy() 将您的文件内容划分为块 - 您可以将它们收集为Collection<List<String>>,或者您可以在收集所有行时应用一些处理(例如,您可以将它们加入单个字符串)。
看看下面的例子:
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
public class ReadFileWithStream {
public static void main(String[] args) throws IOException {
// Path to a file to read
final Path path = Paths.get(ReadFileWithStream.class.getResource("/input.txt").toURI());
final AtomicInteger counter = new AtomicInteger(0);
// Size of a chunk
final int size = 4;
final Collection<List<String>> partitioned = Files.lines(path)
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size))
.values();
partitioned.forEach(System.out::println);
}
}
我的输入文件contains some numbers (one number at a line),当我运行以下代码时,我得到如下内容:
[0, 0, 0, 2]
[0, -3, 2, 0]
[1, -3, -8, 0]
[2, -12, -11, -11]
[-8, -1, -8, 0]
[2, -1, 2, -1]
... and so on
Collectors.groupingBy() 还允许我使用不同的下游收集器。默认情况下使用Collectors.toList(),所以我的结果累积到List<String>,我得到Collection<List<String>>作为最终结果。
假设我想读取 4 大小的块,并且我想将块中的所有数字相加。在这种情况下,我将使用Collectors.summingInt() 作为我的下游函数,返回结果为Collection<Integer>:
final Collection<Integer> partitioned = Files.lines(path)
.collect(Collectors.groupingBy(it -> counter.getAndIncrement() / size, Collectors.summingInt(Integer::valueOf)))
.values();
输出:
2
-1
-10
-32
-17
2
-11
-49
... and so on
最后但并非最不重要。 Collectors.groupingBy() 返回一个映射,其中值按特定键分组。这就是为什么最后我们调用Map.values() 来获取此映射中包含的值的集合。
希望对你有帮助。