1. 概述

本文将探讨在Java中将CSV文件的表头读取为List的几种方法。首先会使用JDK原生类实现,然后介绍如何通过OpenCSV和Apache Commons CSV等第三方库完成相同目标。

✅ 重点覆盖:

  • JDK原生实现方案
  • 主流第三方库对比
  • 完整可执行代码示例

2. 使用BufferedReader

BufferedReader是处理此需求最简单的方案。它通过分块读取内容减少IO操作次数,能高效处理CSV文件

class CsvHeadersAsListUnitTest {

    private static final String CSV_FILE = "src/test/resources/employees.csv";
    private static final String COMMA_DELIMITER = ",";
    private static final List<String> EXPECTED_HEADERS = List.of("ID", "First name", "Last name", "Salary");

    @Test
    void givenCsvFile_whenUsingBufferedReader_thenGetHeadersAsList() throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(CSV_FILE))) {
            String csvHeadersLine = reader.readLine();
            List<String> headers = Arrays.asList(csvHeadersLine.split(COMMA_DELIMITER));
            assertThat(headers).containsExactlyElementsOf(EXPECTED_HEADERS);
        }
    }
}

关键步骤说明:

  1. 使用try-with-resources确保资源自动关闭
  2. 调用readLine()直接读取首行(即表头)
  3. 通过split()切割字符串并用Arrays.asList()转为List

⚠️ 注意:此方法假设表头是文件首行,且不包含换行符等特殊字符

3. 使用Scanner

Scanner类提供了另一种实现思路。顾名思义,它会扫描并解析文件内容

@Test
void givenCsvFile_whenUsingScanner_thenGetHeadersAsList() throws IOException {
    try(Scanner scanner = new Scanner(new File(CSV_FILE))) {
        String csvHeadersLine = scanner.nextLine();
        List<String> headers = Arrays.asList(csvHeadersLine.split(COMMA_DELIMITER));
        assertThat(headers).containsExactlyElementsOf(EXPECTED_HEADERS);
    }
}

与BufferedReader类似:

  • nextLine()方法直接获取文件首行
  • 后续处理逻辑完全相同

✅ 优势:代码更简洁 ❌ 劣势:大文件处理性能不如BufferedReader

4. 使用OpenCSV

OpenCSV是专门处理CSV文件的成熟库。先添加Maven依赖:

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.9</version>
</dependency>

该库提供了开箱即用的CSV解析能力

@Test
void givenCsvFile_whenUsingOpenCSV_thenGetHeadersAsList() throws CsvValidationException, IOException {
    try (CSVReader csvReader = new CSVReader(new FileReader(CSV_FILE))) {
        List<String> headers = Arrays.asList(csvReader.readNext());
        assertThat(headers).containsExactlyElementsOf(EXPECTED_HEADERS);
    }
}

核心特点:

  • CSVReader类封装了文件读取逻辑
  • readNext()方法直接返回String数组形式的表头
  • 自动处理引号、转义符等复杂场景

5. 使用Apache Commons CSV

Apache Commons CSV是另一个强大选择。添加依赖:

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-csv</artifactId>
    <version>1.11.0</version>
</dependency>

CSVParser类提供getHeaderNames()方法直接获取只读表头列表

@Test
void givenCsvFile_whenUsingApacheCommonsCsv_thenGetHeadersAsList() throws IOException {
    CSVFormat csvFormat = CSVFormat.DEFAULT.builder()
      .setDelimiter(COMMA_DELIMITER)
      .setHeader()
      .build();

    try (BufferedReader reader = new BufferedReader(new FileReader(CSV_FILE));
        CSVParser parser = CSVParser.parse(reader, csvFormat)) {
        List<String> headers = parser.getHeaderNames();
        assertThat(headers).containsExactlyElementsOf(EXPECTED_HEADERS);
    }
}

实现要点:

  1. 通过CSVFormat定义解析规则
  2. setHeader()方法自动从首行提取表头
  3. getHeaderNames()返回不可修改的List

✅ 优势:支持更复杂的CSV格式(如自定义分隔符、引号规则等)

6. 总结

本文对比了四种读取CSV表头的方法:

方案 适用场景 优势 劣势
BufferedReader 简单CSV JDK原生,无依赖 需手动处理特殊字符
Scanner 小文件 代码简洁 性能较差
OpenCSV 复杂CSV 功能全面 需引入依赖
Apache Commons CSV 企业级应用 配置灵活 学习曲线稍陡

简单粗暴的选择建议

  • 基础需求 → 用BufferedReader
  • 复杂CSV → 选OpenCSV或Apache Commons CSV

完整示例代码可在GitHub仓库获取


原始标题:Reading CSV Headers Into a List | Baeldung