【问题标题】:Java CSVParser gets empty after reading itJava CSVParser 读取后为空
【发布时间】:2022-01-29 17:07:14
【问题描述】:

在下面的 sn-p 中,我尝试使用 Apache Commons 库中的 CSVParser 读取 excel 文件。问题是为什么records.getRecords(); 使records 的列表为空。我应该如何意识到这种行为?

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

public class ReadCSV {

    public ReadCSV() {
    }

    /* Define headers as enum */
    enum HEADER {
        ID, NAME, AGE
    }

    public List<List<String>> ReadCSVToList(String csvPath) throws IOException, HighBalanceException {
        List<List<String>> csvList = new ArrayList<>();
        try {


            Reader reader = new FileReader(csvPath);
            CSVParser  records = CSVFormat.DEFAULT.withHeader(HEADER.class).parse(reader);
            List<CSVRecord> records1 = records.getRecords();
            System.out.println(records1.size()); // 2
            List<CSVRecord> records2 = records.getRecords();
            System.out.println(records2.size()); // 0

【问题讨论】:

  • 我应该如何知道这种行为 - 阅读您在程序中使用的所有类的文档。

标签: java apache-commons-csv


【解决方案1】:

您可以在官方文档中阅读:CSVParser#getRecords

返回的内容从流中的当前解析位置开始。

在您第一次调用getRecords 时,解析位置位于流的开头。当你第二次调用它时,已经到了流的末尾。

一般来说,我总是建议您从文档开始。通常,只需少量阅读即可轻松回答此类问题。如果仍有令人困惑的方面,社区当然很乐意为您提供进一步的帮助。

【讨论】:

  • 对不起,如果我问了一个不好的问题,我是 java 新手,我怎么知道它正在处理流 "CSVFormat.DEFAULT.withHeader(HEADER.class).parse(reader); "
  • 在 StackOverflow,社区通常会以“阅读文档”作为回应,因为实际上这主要是在回答此类问题。 :)
  • “流”在此上下文中表示输入流,即来自 csv 文件的数据流。如文档中所述,当您访问数据时,会有一个光标移动。
  • 当您重复访问记录时,光标会在流中向前移动。在某个时候,它会走到尽头,您无法读取更多数据。
【解决方案2】:

阅读CSVParser的文档会有所帮助:

根据指定的格式解析 CSV 文件。 [...] 解析器以记录方式工作。一旦从输入流中解析出一条记录,就无法返回。

几段之后,在“解析到内存”标题下:

如果不需要解析记录,则可以将输入的内容完全读入到内存中。

Reader in = new StringReader("a;b\nc;d");
CSVParser parser = new CSVParser(in, CSVFormat.EXCEL);
List<CSVRecord> list = parser.getRecords();

必须牢记两个约束:

  1. 从解析器的当前位置开始解析到内存。如果您已经从输入中解析了记录,那么这些记录将不会出现在您的 CSV 数据的内存表示中。
  2. 解析到内存可能会消耗大量系统资源,具体取决于输入。例如,如果您要解析 150MB 的 CSV 数据文件,则内容将完全读入内存。

当您第一次调用 records.getRecords() 时,您正在将 CSV 文件完全读入内存。再加上“从解析器的当前位置开始解析到内存”这一事实意味着对于第二次调用,没有更多的记录要解析(因为解析器已经完全读取了文件。)

【讨论】:

    猜你喜欢
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    • 1970-01-01
    • 2015-04-03
    • 1970-01-01
    相关资源
    最近更新 更多