使用Java Streams一次从文本文件中读取X行吗? [英] Read X lines at a time from a text file using Java Streams?

查看:81
本文介绍了使用Java Streams一次从文本文件中读取X行吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个普通的旧文本文件",其中的行以换行符结尾.由于种种原因,我需要一次读取并解析此文本文件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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆