1. 概述
CSV 是系统间和应用程序之间常见的数据交换格式。一个常见的场景是构建处理这些CSV文件的 Java 应用程序。当我们需要将普通的 Java 对象(Plain Old Java Object,简称 POJO)映射到 CSV 格式时,就需要进行这样的操作。
在这个教程中,我们将学习如何使用自定义位置和标题名称将 POJO 映射到 CSV 格式。
2. OpenCSV 库
OpenCSV 是处理 CSV 文件的流行库。首先,我们需要在项目中添加 Maven 依赖:
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.9</version>
</dependency>
3. 生成输入记录
本文我们将生成示例输入记录,然后将它们转换为 CSV 记录。
3.1. 应用程序记录
应用程序记录是一个简单的 POJO,包含 id
、name
、age
和 created_at
字段:
3.2. 应用程序列表
我们将生成一个应用程序列表,稍后将转换为 CSV 格式:
List<Application> applications = List.of(
new Application("123", "Sam", 34, "2023-08-11"),
new Application("456", "Tam", 44, "2023-02-11"),
new Application("890", "Jam", 54, "2023-03-11")
);
4. POJO 映射到 CSV
默认情况下,POJO 映射到 CSV 的过程很简单。我们可以使用 StatefulBeanToCsvBuilder
,并定义分隔符和其他配置,然后通过 FilerWriter
写入:
public static void beanToCSVWithDefault(List<Application> applications) throws Exception {
try (FileWriter writer = new FileWriter("application.csv")) {
var builder = new StatefulBeanToCsvBuilder<Application>(writer)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withSeparator(',')
.build();
builder.write(applications);
}
}
默认映射会将 POJO 映射到 CSV,字段名称按升序排列,但如果希望标题采用自定义格式,这就不适用了。
4.1. 自定义标题策略
如果我们希望输出的 CSV 文件具有自定义标题,我们可以在写入 CSV 文件时定义并使用自定义标题策略。
例如,如果我们希望标题全部小写,可以重写 generateHeader:
方法:
public class CustomCSVWriterStrategy<T> extends HeaderColumnNameMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
String[] header = super.generateHeader(bean);
return Arrays.stream(header)
.map(String::toLowerCase)
.toArray(String[]::new);
}
}
一旦有了自定义标题映射策略,我们就可以构建 StatefulBeanToCsvBuilder
,然后以 CSV 格式将 POJO 写入 CSV 文件:
public static void beanToCSVWithCustomHeaderStrategy(List<Application> applications)
throws IOException, CsvRequiredFieldEmptyException, CsvDataTypeMismatchException {
try (FileWriter writer = new FileWriter("application.csv")){
var mappingStrategy = new CustomCSVWriterStrategy<Application>();
mappingStrategy.setType(Application.class);
var builder = new StatefulBeanToCsvBuilder<Application>(writer)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withMappingStrategy(mappingStrategy)
.build();
builder.write(applications);
}
}
4.2. 自定义位置策略
将具有特定定义位置的 CSV 字段写入 CSV 文件也是可能的。 我们只需在应用程序记录属性上添加所需的字段位置注解即可:
public record Application(
@CsvBindByPosition(position = 0)
String id,
@CsvBindByPosition(position = 1)
String name,
@CsvBindByPosition(position = 2)
Integer age,
@CsvBindByPosition(position = 3)
String created_at) {}
现在,我们可以使用带有注解的 Application
记录将 POJO 映射到 CSV 格式:
public static void beanToCSVWithCustomPositionStrategy(List<Application> applications) throws Exception {
try (FileWriter writer = new FileWriter("application3.csv")) {
var builder = new StatefulBeanToCsvBuilder<Application1>(writer)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.build();
builder.write(applications);
}
}
4.3. 自定义位置策略和标题名称
如果希望在特定位置同时包含 CSV 字段和标题,我们可以使用自定义列定位策略实现。
首先,我们需要在应用程序记录类属性上添加位置和标题名称注解:
public record Application1(
@CsvBindByName(column = "id", required = true)
@CsvBindByPosition(position = 1)
String id,
@CsvBindByName(column = "name", required = true)
@CsvBindByPosition(position = 0)
String name,
@CsvBindByName(column = "age", required = true)
@CsvBindByPosition(position = 2)
Integer age,
@CsvBindByName(column = "position", required = true)
@CsvBindByPosition(position = 3)
String created_at) {}
准备好记录类后,我们需要编写自定义列定位策略。这个策略将包含生成标题和字段位置的逻辑:
public class CustomColumnPositionStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader(T bean) throws CsvRequiredFieldEmptyException {
super.generateHeader(bean);
return super.getColumnMapping();
}
}
现在,我们已经完成了记录和列定位策略,可以将其用于客户端逻辑中,生成 CSV 文件:
public static void beanToCSVWithCustomHeaderAndPositionStrategy(List<Application1> applications)
throws IOException, CsvRequiredFieldEmptyException, CsvDataTypeMismatchException {
try (FileWriter writer = new FileWriter("application4.csv")){
var mappingStrategy = new CustomColumnPositionStrategy<Application1>();
mappingStrategy.setType(Application1.class);
var builder = new StatefulBeanToCsvBuilder<Application1>(writer)
.withQuotechar(CSVWriter.NO_QUOTE_CHARACTER)
.withMappingStrategy(mappingStrategy)
.build();
builder.write(applications);
}
}
5. 总结
在这篇教程中,我们学习了如何将 POJO 转换为 CSV 格式并写入 CSV 文件。我们讨论了包括 CSV 字段标题的方法,并提供了自定义标题和位置策略的例子。
OpenCSV 并没有提供一个内置的解决方案来为 CSV 文件设置自定义位置和标题,但很容易编写自定义策略来将字段和标题放在所需的位置。
如往常一样,示例代码可在 GitHub 上查看。