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

我正在尝试读取包含多列的 csv 文件。第一行始终是 csv 文件的标题。我想将 csv 数据转换为 JSON。我可以将其读取为字符串并转换为 JSON,但我无法为其分配标头。


例如输入 csv 看起来像:


first_name,last_name

A,A1

B,B1

C,C1


Stream<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 格式?


富国沪深
浏览 346回答 3
3回答

杨魅力

我将分两步解决这个问题:首先,阅读标题,然后阅读其余的行:static String[] headers(String path) throws IOException {&nbsp; &nbsp; try (BufferedReader br = new BufferedReader(new FileReader(path))) {&nbsp; &nbsp; &nbsp; &nbsp; return br.readLine().split(",");&nbsp; &nbsp; }}现在,您可以使用上述方法如下:String path = "sample.csv";// Read headersString[] headers = headers(path);List<Map<String, String>> result = null;// Read datatry (Stream<String> stream = Files.lines(Paths.get(path))) {&nbsp; &nbsp; result = stream&nbsp; &nbsp; &nbsp; &nbsp; .skip(1) // skip headers&nbsp; &nbsp; &nbsp; &nbsp; .map(line -> line.split(","))&nbsp; &nbsp; &nbsp; &nbsp; .map(data -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Map<String, String> map = new HashMap<>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < data.length; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;map.put(headers[i], data[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map;&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());}您可以for在第二个map操作中更改循环:try (Stream<String> stream = Files.lines(Paths.get(path))) {&nbsp; &nbsp; result = stream&nbsp; &nbsp; &nbsp; &nbsp; .skip(1) // skip headers&nbsp; &nbsp; &nbsp; &nbsp; .map(line -> line.split(","))&nbsp; &nbsp; &nbsp; &nbsp; .map(data -> IntStream.range(0, data.length)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .boxed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toMap(i -> headers[i], i -> data[i])))&nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList());}编辑:如果不是收集到列表,而是要对从每一行读取的地图执行操作,您可以按如下方式进行:try (Stream<String> stream = Files.lines(Paths.get(path))) {&nbsp; &nbsp; stream&nbsp; &nbsp; &nbsp; &nbsp; .skip(1) // skip headers&nbsp; &nbsp; &nbsp; &nbsp; .map(line -> line.split(","))&nbsp; &nbsp; &nbsp; &nbsp; .map(data -> IntStream.range(0, data.length)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .boxed()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toMap(i -> headers[i], i -> data[i])))&nbsp; &nbsp; &nbsp; &nbsp; .forEach(System.out::println);}(这里的动作是打印每张地图)。这个版本可以改进,即它装箱ints的流,然后int再次拆箱以将其用作headers和data数组的索引。此外,可以通过将每个映射的创建提取到私有方法来提高可读性。注意:也许读取文件两次不是性能方面的最佳方法,但代码简单且富有表现力。除此之外,null处理、数据转换(即到数字或日期等)和边界情况(即没有标题、没有数据行或数据数组的不同长度等)留给读者作为练习;)

月关宝盒

我认为这就是你想要做的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 {&nbsp; &nbsp; public static void main(String[] args) throws JsonProcessingException, IOException {&nbsp; &nbsp; &nbsp; &nbsp; Stream<String> stream = Files.lines(Paths.get("src/main/resources/test1.csv"));&nbsp; &nbsp; &nbsp; &nbsp; List<Map<String, Object>> readall = stream.map(l -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Map<String, Object> map = new HashMap<String, Object>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String[] values = l.split(",");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("name", values[0]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; map.put("age", values[1]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return map;&nbsp; &nbsp; &nbsp; &nbsp; }).collect(Collectors.toList());&nbsp; &nbsp; &nbsp; &nbsp; ObjectMapper mapperObj = new ObjectMapper();&nbsp; &nbsp; &nbsp; &nbsp; String jsonResp = mapperObj.writeValueAsString(readall);&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(jsonResp);&nbsp; &nbsp; }}与 Java -8 Streams 一起使用,带有标头,并使用 jackson 将其转换为 json。使用过的 CSVabc,20bbc,30

当年话下

很简单,不要把它转换成字符串列表。将其转换为 HashMap 列表,然后使用 org.json 库将其转换为 json 。使用 jackson 将 CSV 转换为 Hashmap让输入流为InputStream stream = new FileInputStream(new File("filename.csv"));示例:将 CSV 转换为 HashMappublic List<Map<String, Object>> read(InputStream stream) throws JsonProcessingException, IOException {&nbsp;List<Map<String, Object>> response = new LinkedList<Map<String, Object>>();&nbsp;CsvMapper mapper = new CsvMapper();&nbsp;CsvSchema schema = CsvSchema.emptySchema().withHeader();&nbsp;MappingIterator<Map<String, String>> iterator = mapper.reader(Map.class).with(schema).readValues(stream);&nbsp;while (iterator.hasNext())&nbsp;&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp;response.add(Collections.<String, Object>unmodifiableMap(iterator.next()));&nbsp;}&nbsp;return response;&nbsp;}将地图列表转换为 JsonJSONArray jsonArray = new JSONArray(response);System.out.println(jsonArray.toString());
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java