为了账号安全,请及时绑定邮箱和手机立即绑定

读取一个巨大的 csv 文件并使用 Java 8 转换为 JSON

读取一个巨大的 csv 文件并使用 Java 8 转换为 JSON

富国沪深 2021-09-29 15:25:51
我正在尝试读取包含多列的 csv 文件。第一行始终是 csv 文件的标题。我想将 csv 数据转换为 JSON。我可以将其读取为字符串并转换为 JSON,但我无法为其分配标头。例如输入 csv 看起来像:first_name,last_nameA,A1B,B1C,C1Stream<String> stream = Files.lines(Paths.get("sample.csv"))List<String[]> readall = stream.map(l -> l.split(",")).collect(Collectors.toList()); 或者List<String> test1 = readall.stream().skip(0).map(row -> row[1]).collect(Collectors.toList());并且使用 com.fasterxml.jackson.databind.ObjectMapper 的 WriteValueAsString 只会创建没有标头的 JSON。我希望输出格式为{[{"first_name":"A","last_name":"A1"},{"first_name":"B"....如何在 Java 中使用流来准备这种 JSON 格式?
查看完整描述

3 回答

?
杨魅力

TA贡献1811条经验 获得超6个赞

我将分两步解决这个问题:首先,阅读标题,然后阅读其余的行:


static String[] headers(String path) throws IOException {


    try (BufferedReader br = new BufferedReader(new FileReader(path))) {

        return br.readLine().split(",");

    }

}

现在,您可以使用上述方法如下:


String path = "sample.csv";


// Read headers

String[] headers = headers(path);


List<Map<String, String>> result = null;


// Read data

try (Stream<String> stream = Files.lines(Paths.get(path))) {

    result = stream

        .skip(1) // skip headers

        .map(line -> line.split(","))

        .map(data -> {

            Map<String, String> map = new HashMap<>();

            for (int i = 0; i < data.length; i++) {

               map.put(headers[i], data[i]);

            }

            return map;

        })

        .collect(Collectors.toList());

}

您可以for在第二个map操作中更改循环:


try (Stream<String> stream = Files.lines(Paths.get(path))) {

    result = stream

        .skip(1) // skip headers

        .map(line -> line.split(","))

        .map(data -> IntStream.range(0, data.length)

            .boxed()

            .collect(Collectors.toMap(i -> headers[i], i -> data[i])))

        .collect(Collectors.toList());

}

编辑:如果不是收集到列表,而是要对从每一行读取的地图执行操作,您可以按如下方式进行:


try (Stream<String> stream = Files.lines(Paths.get(path))) {

    stream

        .skip(1) // skip headers

        .map(line -> line.split(","))

        .map(data -> IntStream.range(0, data.length)

            .boxed()

            .collect(Collectors.toMap(i -> headers[i], i -> data[i])))

        .forEach(System.out::println);

}

(这里的动作是打印每张地图)。


这个版本可以改进,即它装箱ints的流,然后int再次拆箱以将其用作headers和data数组的索引。此外,可以通过将每个映射的创建提取到私有方法来提高可读性。


注意:也许读取文件两次不是性能方面的最佳方法,但代码简单且富有表现力。除此之外,null处理、数据转换(即到数字或日期等)和边界情况(即没有标题、没有数据行或数据数组的不同长度等)留给读者作为练习;)


查看完整回答
反对 回复 2021-09-29
?
月关宝盒

TA贡献1772条经验 获得超5个赞

我认为这就是你想要做的


import java.io.IOException;

import java.nio.file.Files;

import java.nio.file.Paths;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import java.util.stream.Collectors;

import java.util.stream.Stream;


import com.fasterxml.jackson.core.JsonProcessingException;

import com.fasterxml.jackson.databind.ObjectMapper;


public class App {

    public static void main(String[] args) throws JsonProcessingException, IOException {


        Stream<String> stream = Files.lines(Paths.get("src/main/resources/test1.csv"));

        List<Map<String, Object>> readall = stream.map(l -> {

            Map<String, Object> map = new HashMap<String, Object>();

            String[] values = l.split(",");


            map.put("name", values[0]);

            map.put("age", values[1]);


            return map;

        }).collect(Collectors.toList());


        ObjectMapper mapperObj = new ObjectMapper();

        String jsonResp = mapperObj.writeValueAsString(readall);

        System.out.println(jsonResp);


    }

}

与 Java -8 Streams 一起使用,带有标头,并使用 jackson 将其转换为 json。使用过的 CSV


abc,20

bbc,30


查看完整回答
反对 回复 2021-09-29
?
当年话下

TA贡献1890条经验 获得超9个赞

很简单,不要把它转换成字符串列表。将其转换为 HashMap 列表,然后使用 org.json 库将其转换为 json 。使用 jackson 将 CSV 转换为 Hashmap


让输入流为


InputStream stream = new FileInputStream(new File("filename.csv"));

示例:将 CSV 转换为 HashMap


public List<Map<String, Object>> read(InputStream stream) throws JsonProcessingException, IOException {

 List<Map<String, Object>> response = new LinkedList<Map<String, Object>>();

 CsvMapper mapper = new CsvMapper();

 CsvSchema schema = CsvSchema.emptySchema().withHeader();

 MappingIterator<Map<String, String>> iterator = mapper.reader(Map.class).with(schema).readValues(stream);

 while (iterator.hasNext()) 

 {

       response.add(Collections.<String, Object>unmodifiableMap(iterator.next()));

 }

 return response;

 }

将地图列表转换为 Json


JSONArray jsonArray = new JSONArray(response);

System.out.println(jsonArray.toString());


查看完整回答
反对 回复 2021-09-29
  • 3 回答
  • 0 关注
  • 345 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信