如何将CSV文件转换为List <Map <String,String >>

Viv*_*ari 2 java java-8 java-stream

我有一个CSV文件,第一行有一个标题.我想将其转换为List<Map<String, String>>,其中Map<String, String>列表中的每个代表文件中的记录.地图的关键是标题,值是字段的实际值.到目前为止我所拥有的:

BufferedReader br = <handle to file>;
// Get the headers to build the map.
String[] headers = br.lines().limit(1).collect(Collectors.toArray(size -> new String[size]));
Stream<String> recordStream = br.lines().skip(1);
Run Code Online (Sandbox Code Playgroud)

我可以执行哪些进一步操作recordStream以便将其转换为List<Map<String, String>>

示例CSV文件是:

header1,header2,header3   ---- Header line
field11,field12,field13   ----> need to transform to Map where entry would be like header1:field11 header2:field12 and so on.
field21,field22,field23
field31,field32,field33
Run Code Online (Sandbox Code Playgroud)

最后,需要将所有这些地图收集到列表中.

Tun*_*aki 6

以下将有效.通过readLine直接调用BufferedReader和分割来检索标题行,.然后,读取文件的其余部分:每行分开,并映射到Map具有相应标题的a.

try (BufferedReader br = new BufferedReader(...)) {
    String[] headers = br.readLine().split(",");
    List<Map<String, String>> records = 
            br.lines().map(s -> s.split(","))
                      .map(t -> IntStream.range(0, t.length)
                                         .boxed()
                                         .collect(toMap(i -> headers[i], i -> t[i])))
                      .collect(toList());
    System.out.println(headers);
    System.out.println(records);
};
Run Code Online (Sandbox Code Playgroud)

这里一个非常重要的注意事项是,当它被调用时BufferedReader.lines()不会返回新的Stream:我们读取标题后不得跳过1行,因为读者已经进入下一行.

作为旁注,我使用了一个try-with-resources结构,以便BufferedReader可以正确关闭.

  • 作为旁注,我仍然建议使用像[Commons CSV](https://commons.apache.org/proper/commons-csv/)这样的库来读取CSV.[CSV格式](http://tools.ietf.org/html/rfc4180)支持引号,允许在字段内使用逗号.提供的实现将错误地读取此类文件. (2认同)