将 CSV 文件作为行流读取 - 在读取整个文件之前处理每一行[重复]

问题描述 投票:0回答:1

我读了这样的文件:

try (Stream<String> lines = java.nio.file.Files.lines(Path.of(filePath), StandardCharsets.UTF_8)) {
    lines.skip(1).forEach(line -> {
        handleLine(line);
    });

这让我可以在文件完全读取之前对其进行处理。我想对 CSV 文件执行相同的操作,并获得 CSV 阅读器具有的解析功能,例如将每个字段映射到其标头。

java java-stream filereader csvreader
1个回答
0
投票

“...我想对 csv 文件执行相同的操作,并获得 csv 阅读器具有的解析功能,例如将每个字段映射到其标题。...”

您需要首先收集 header 值。
我建议只使用 ScannerBufferedReader 类来返回第一行。

然后,重新实例化对象,并评估 stream

这是一个例子。
我正在利用 local-class 来枚举 header 值,并使用 LinkedHashMap 封装来提供 get 方法。

record Header(String s, int i) { }
class CSVMap extends LinkedHashMap<Header, List<String>> {
    List<String> get(int i) {
        for (Map.Entry<Header, List<String>> e : entrySet())
            if (e.getKey().i == i) return e.getValue();
        return null;
    }
}
BufferedReader br = new BufferedReader(new FileReader("data.csv"));
CSVMap map = new CSVMap();
int i = 0;
for (String s : br.readLine().split(","))
    map.put(new Header(s, i++), new ArrayList<>());
br.close();
br = new BufferedReader(new FileReader("data.csv"));
br.lines()
  .skip(1)
  .forEach(x -> {
      String[] s = x.split(",");
      IntStream.range(0, s.length)
               .forEach(y -> map.get(y).add(s[y]));
  });
br.close();

map.forEach((k, v) -> {
    System.out.printf("'%s' (%d):  %s%n", k.s, k.i, v);
});

数据.csv

a,b,c,d
1,2,3,4
9,8,7,6

输出

'a' (0):  [1, 9]
'b' (1):  [2, 8]
'c' (2):  [3, 7]
'd' (3):  [4, 6]
© www.soinside.com 2019 - 2024. All rights reserved.