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);
}
}
}
关键步骤说明:
- 使用try-with-resources确保资源自动关闭
- 调用
readLine()
直接读取首行(即表头) - 通过
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);
}
}
实现要点:
- 通过
CSVFormat
定义解析规则 setHeader()
方法自动从首行提取表头getHeaderNames()
返回不可修改的List
✅ 优势:支持更复杂的CSV格式(如自定义分隔符、引号规则等)
6. 总结
本文对比了四种读取CSV表头的方法:
方案 | 适用场景 | 优势 | 劣势 |
---|---|---|---|
BufferedReader | 简单CSV | JDK原生,无依赖 | 需手动处理特殊字符 |
Scanner | 小文件 | 代码简洁 | 性能较差 |
OpenCSV | 复杂CSV | 功能全面 | 需引入依赖 |
Apache Commons CSV | 企业级应用 | 配置灵活 | 学习曲线稍陡 |
简单粗暴的选择建议:
- 基础需求 → 用BufferedReader
- 复杂CSV → 选OpenCSV或Apache Commons CSV
完整示例代码可在GitHub仓库获取