3

我想处理这种结构的 CSV 文件:

header1,header2
val1.1, val1.2
val2.1, val2.2

但前提是第一行包含两个标题名称 - 否则抛出异常。

我目前使用Apache Common CSV的实现是:

Reader reader = new InputStreamReader(new ByteArrayInputStream(file.getContent()));

CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
            .withHeader("header1", "header2")
            .withSkipHeaderRecord());

for (CSVRecord csvRecord : csvParser) { /* records processing */ }

问题是第一行的值可能与标题名称不同,并且文件仍在处理中。

4

1 回答 1

0

参考CSVFormat 的Java Doc

安全地引用列

如果您的源代码包含标题记录,您可以通过使用不带参数的 withHeader(String...) 来简化代码并安全地引用列:

 CSVFormat.EXCEL.withHeader();

这会导致解析器读取第一条记录并将其值用作列名。然后,调用采用 String 列名参数的 CSVRecord get 方法之一:

 String value = record.get("Col1");

这使您的代码不受 CSV 文件中列顺序更改的影响。


所以你可以按照这个并使用第一行作为标题,然后验证标题CSVParser#getHeaderNames

下面是一个简单的演示:

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

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

public class UseFirstRowAsHeader {
    public static void main(String[] args) throws IOException {
        String validHeaderCsv = "header1,header2\r\n"
                + "val1.1,val1.2\r\n"
                + "val2.1,val2.2";
        parseWithHeaderValidation(validHeaderCsv);
        String invalidHeaderCsv = "header1,header2,header3\r\n"
                + "val1.1,val1.2\r\n"
                + "val2.1,val2.2";
        parseWithHeaderValidation(invalidHeaderCsv);
    }

    private static void parseWithHeaderValidation(String validHeaderCsv) throws IOException {
        Reader reader = new StringReader(validHeaderCsv);
        List<String> expectedHeaders = new ArrayList<String>();
        expectedHeaders.add("header1");
        expectedHeaders.add("header2");
        try (CSVParser csvParser = new CSVParser(reader, CSVFormat.DEFAULT
                .withHeader().withAllowMissingColumnNames(false)
                .withSkipHeaderRecord())) {
            if (!csvParser.getHeaderNames().equals(expectedHeaders)) {
                throw new IllegalStateException("Not expected headers" + csvParser.getHeaderNames());
            }

            for (CSVRecord csvRecord : csvParser) {
                System.out.println(csvRecord.get("header1") + "," + csvRecord.get("header2"));
            }
        }
    }
}
于 2021-01-15T13:56:21.203 回答