使用Java Streams一次从文本文件中读取X行吗? [英] Read X lines at a time from a text file using Java Streams?
问题描述
我有一个普通的旧文本文件",其中的行以换行符结尾.由于种种原因,我需要一次读取并解析此文本文件4行(一般来说X).
I have a "plain old text file" where lines end with a new line character. For arbitrary reasons I need to read and parse this text file 4 (X for generality) lines at a time.
我想使用Java流执行此任务,并且我知道可以将文件转换为流,如下所示:
I'd like to use Java streams for this task and I know I can turn the file into a stream like so:
try (Stream<String> stream = Files.lines(Paths.get("file.txt""))) {
stream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
但是如何使用Java的Stream API将文件捆绑"成4个连续的行呢?
But how can I use Java's Stream API to "bunch" the file into groups of 4 consecutive lines?
推荐答案
有一种使用标准Java 8 Stream API将文件内容分区和处理为n
大小的块的方法.您可以使用
There is a way to partition and process your file content into n
-size chunks using standard Java 8 Stream API. You can use Collectors.groupingBy()
to partition your file content into chunks - you can collect them as a Collection<List<String>>
or you can apply some processing while collecting all lines (e.g. you can join them to a single 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);
}
}
我的输入文件包含一些数字(在某行中包含一个数字) ,当我运行以下代码时,我得到类似的东西:
My input file contains some numbers (one number at a line), and when I run following code I get something like:
[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.toList()
被使用,所以我的结果被累加到List<String>
中,并且得到Collection<List<String>>
作为最终结果.
Collectors.groupingBy()
allows me also to use different downstream collector. By default Collectors.toList()
is being used so my result is accumulated into a List<String>
and I get Collection<List<String>>
as a final result.
比方说,我想读取4位数的数据块,并且我希望对一个数据块中的所有数字求和.在这种情况下,我将使用 Collectors.summingInt()
作为我的下游函数,返回的结果是Collection<Integer>
:
Let's say I want to read 4-size chunks and I want to sum all numbers in a chunk. In this case I will use Collectors.summingInt()
as my downstream function and the returned result is 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()
以获取此映射中包含的值的集合.
And last but not least. Collectors.groupingBy()
returns a map where values are grouped by specific keys. That's why in the end we call Map.values()
to get a collection of the values this contained in this map.
希望有帮助.
这篇关于使用Java Streams一次从文本文件中读取X行吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!