1. 简介
本文将带你快速上手 OpenCSV 4,一个用于处理 CSV 文件的强大 Java 库。它支持 CSV 文件的读写、序列化、反序列化及解析等操作。我们将通过多个示例,演示如何配置和使用 OpenCSV 4 完成实际开发任务。
2. 环境配置
首先通过 Maven 依赖引入 OpenCSV:
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.8</version>
</dependency>
JAR 包可从 官网 或 Maven 中央仓库 获取。
本文使用的示例 CSV 文件结构简单,包含两列四行:
colA,colB
A,B
C,D
G,G
G,F
3. 使用 Bean 还是原生 API
引入依赖后,可通过两种方式处理 CSV:
- 原生 API:使用
CSVReader
/CSVWriter
(适合简单操作) - Bean 映射:使用
CsvToBean
将 CSV 转换为注解化的 POJO 对象
本文聚焦同步(阻塞)操作,异步处理将在后续文章讨论。⚠️ 同步方法会阻塞后续代码执行,生产环境建议改用异步方案。
3.1. CSVReader 原生读取
CSVReader
提供 readAll()
和 readNext()
两种读取方式。先看 readAll()
同步读取全量数据:
public List<String[]> readAllLines(Path filePath) throws Exception {
try (Reader reader = Files.newBufferedReader(filePath)) {
try (CSVReader csvReader = new CSVReader(reader)) {
return csvReader.readAll();
}
}
}
调用方式:
public List<String[]> readAllLinesExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI()
);
return CsvReaderExamples.readAllLines(path);
}
再看 readNext()
逐行读取:
public List<String[]> readLineByLine(Path filePath) throws Exception {
List<String[]> list = new ArrayList<>();
try (Reader reader = Files.newBufferedReader(filePath)) {
try (CSVReader csvReader = new CSVReader(reader)) {
String[] line;
while ((line = csvReader.readNext()) != null) {
list.add(line);
}
}
}
return list;
}
调用方式:
public List<String[]> readLineByLineExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI()
);
return CsvReaderExamples.readLineByLine(path);
}
进阶用法:使用 CSVReaderBuilder
灵活配置
CSVParser parser = new CSVParserBuilder()
.withSeparator(',')
.withIgnoreQuotations(true)
.build();
CSVReader csvReader = new CSVReaderBuilder(reader)
.withSkipLines(0)
.withCSVParser(parser)
.build();
✅ CSVReaderBuilder
支持跳过表头、自定义分隔符、处理引号等配置。更多参数见官方文档。
踩坑提醒:务必关闭 Reader 防止内存泄漏!
3.2. CSVWriter 原生写入
CSVWriter
支持逐行写入或全量写入。先看逐行写入:
public String writeLineByLine(List<String[]> lines, Path path) throws Exception {
try (CSVWriter writer = new CSVWriter(new FileWriter(path.toString()))) {
for (String[] line : lines) {
writer.writeNext(line);
}
}
return Helpers.readFile(path);
}
调用方式:
public String writeLineByLineExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenOneByOne.csv").toURI()
);
return CsvWriterExamples.writeLineByLine(Helpers.fourColumnCsvString(), path);
}
再看全量写入:
public String writeAllLines(List<String[]> lines, Path path) throws Exception {
try (CSVWriter writer = new CSVWriter(new FileWriter(path.toString()))) {
writer.writeAll(lines);
}
return Helpers.readFile(path);
}
调用方式:
public String writeAllLinesExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenAll.csv").toURI()
);
return CsvWriterExamples.writeAllLines(Helpers.fourColumnCsvString(), path);
}
3.3. Bean 映射读取
OpenCSV 可将 CSV 映射为注解化的 POJO Bean。推荐使用 CsvToBeanBuilder
(OpenCSV 4+ 标准用法)。
示例 Bean 定义:
public class SimplePositionBean {
@CsvBindByPosition(position = 0)
private String exampleColOne;
@CsvBindByPosition(position = 1)
private String exampleColTwo;
// getters and setters
}
✅ 通过 @CsvBindByPosition
按列位置映射,或用 @CsvBindByName
按列名映射。
创建通用基类提升复用性:
public class CsvBean { }
子类示例(按列名映射):
public class NamedColumnBean extends CsvBean {
@CsvBindByName(column = "name")
private String name;
// 自动推断列名为 'Age'
@CsvBindByName
private int age;
// getters and setters
}
同步读取实现:
public List<CsvBean> beanBuilderExample(Path path, Class clazz) throws Exception {
CsvTransfer csvTransfer = new CsvTransfer();
try (Reader reader = Files.newBufferedReader(path)) {
CsvToBean<CsvBean> cb = new CsvToBeanBuilder<CsvBean>(reader)
.withType(clazz)
.build();
csvTransfer.setCsvList(cb.parse());
}
return csvTransfer.getCsvList();
}
调用方式(位置映射):
public List<CsvBean> simplePositionBeanExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/twoColumn.csv").toURI()
);
return BeanExamples.beanBuilderExample(path, SimplePositionBean.class);
}
调用方式(列名映射):
public List<CsvBean> namedColumnBeanExample() throws Exception {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/namedColumn.csv").toURI()
);
return BeanExamples.beanBuilderExample(path, NamedColumnBean.class);
}
3.4. Bean 映射写入
使用 StatefulBeanToCsv
将 Bean 写入 CSV:
public String writeCsvFromBean(Path path) throws Exception {
List<CsvBean> sampleData = Arrays.asList(
new WriteExampleBean("Test1", "sfdsf", "fdfd"),
new WriteExampleBean("Test2", "ipso", "facto")
);
try (Writer writer = new FileWriter(path.toString())) {
StatefulBeanToCsv<CsvBean> sbc = new StatefulBeanToCsvBuilder<CsvBean>(writer)
.withQuotechar('\'')
.withSeparator(CSVWriter.DEFAULT_SEPARATOR)
.build();
sbc.write(sampleData);
}
return Helpers.readFile(path);
}
调用方式:
public String writeCsvFromBeanExample() {
Path path = Paths.get(
ClassLoader.getSystemResource("csv/writtenBean.csv").toURI()
);
return BeanExamples.writeCsvFromBean(path);
}
4. 总结
本文介绍了 OpenCSV 的同步操作方案,涵盖:
- 原生
CSVReader
/CSVWriter
API - Bean 映射的读写操作