java – OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?
作者:互联网
我创建了一个MappingsBean类,其中指定了CSV文件的所有列.接下来,我解析XML文件并创建mappingbeans列表.然后我将该数据写入CSV文件作为报告.
我正在使用以下注释:
public class MappingsBean {
@CsvBindByName(column = "TradeID")
@CsvBindByPosition(position = 0)
private String tradeId;
@CsvBindByName(column = "GWML GUID", required = true)
@CsvBindByPosition(position = 1)
private String gwmlGUID;
@CsvBindByName(column = "MXML GUID", required = true)
@CsvBindByPosition(position = 2)
private String mxmlGUID;
@CsvBindByName(column = "GWML File")
@CsvBindByPosition(position = 3)
private String gwmlFile;
@CsvBindByName(column = "MxML File")
@CsvBindByPosition(position = 4)
private String mxmlFile;
@CsvBindByName(column = "MxML Counterparty")
@CsvBindByPosition(position = 5)
private String mxmlCounterParty;
@CsvBindByName(column = "GWML Counterparty")
@CsvBindByPosition(position = 6)
private String gwmlCounterParty;
}
然后我使用StatefulBeanToCsv类写入CSV文件:
File reportFile = new File(reportOutputDir + "/" + REPORT_FILENAME);
Writer writer = new PrintWriter(reportFile);
StatefulBeanToCsv<MappingsBean> beanToCsv = new
StatefulBeanToCsvBuilder(writer).build();
beanToCsv.write(makeFinalMappingBeanList());
writer.close();
这种方法的问题是如果我使用@CsvBindByPosition(position = 0)来控制
位置然后我无法生成列名称.如果我使用@CsvBindByName(column =“TradeID”),那么我无法设置列的位置.
有没有办法可以同时使用两个注释,这样我就可以创建带有列标题的CSV文件并控制列位置?
问候,
维克拉姆帕特哈尼亚
解决方法:
我有类似的问题. AFAIK OpenCSV中没有内置功能,允许使用自定义列名和顺序将bean写入CSV.
开箱即用的OpenCSV中有两个主要的MappingStrategyies:
> HeaderColumnNameMappingStrategy:允许根据自定义名称将CVS文件列映射到bean字段;将bean写入CSV时,这允许更改列标题名称,但我们无法控制列顺序
> ColumnPositionMappingStrategy:允许根据列顺序将CSV文件列映射到bean字段;在将bean写入CSV时,我们可以控制列顺序但是我们得到一个空头(实现返回新的String [0]作为标题)
我发现实现自定义列名和排序的唯一方法是编写自定义MappingStrategy.
第一个解决方案:快速简便但硬编码
创建自定义MappingStrategy:
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
private static final String[] HEADER = new String[]{"TradeID", "GWML GUID", "MXML GUID", "GWML File", "MxML File", "MxML Counterparty", "GWML Counterparty"};
@Override
public String[] generateHeader() {
return HEADER;
}
}
并在StatefulBeanToCsvBuilder中使用它:
final CustomMappingStrategy<MappingsBean> mappingStrategy = new CustomMappingStrategy<>();
mappingStrategy.setType(MappingsBean.class);
final StatefulBeanToCsv<MappingsBean> beanToCsv = new StatefulBeanToCsvBuilder<MappingsBean>(writer)
.withMappingStrategy(mappingStrategy)
.build();
beanToCsv.write(makeFinalMappingBeanList());
writer.close()
在MappingsBean类中,我们保留了CsvBindByPosition注释 – 以控制排序(在此解决方案中,不需要CsvBindByName注释).由于自定义映射策略,标题列名称包含在生成的CSV文件中.
这个解决方案的缺点是,当我们通过CsvBindByPosition注释更改列排序时,我们必须在自定义映射策略中手动更改HEADER常量.
第二种解决方案:更灵活
第一个解决方案有效,但对我来说并不好.基于MappingStrategy的内置实现,我提出了另一个实现:
class CustomMappingStrategy<T> extends ColumnPositionMappingStrategy<T> {
@Override
public String[] generateHeader() {
final int numColumns = findMaxFieldIndex();
if (!isAnnotationDriven() || numColumns == -1) {
return super.generateHeader();
}
header = new String[numColumns + 1];
BeanField beanField;
for (int i = 0; i <= numColumns; i++) {
beanField = findField(i);
String columnHeaderName = extractHeaderName(beanField);
header[i] = columnHeaderName;
}
return header;
}
private String extractHeaderName(final BeanField beanField) {
if (beanField == null || beanField.getField() == null || beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class).length == 0) {
return StringUtils.EMPTY;
}
final CsvBindByName bindByNameAnnotation = beanField.getField().getDeclaredAnnotationsByType(CsvBindByName.class)[0];
return bindByNameAnnotation.column();
}
}
您可以在StatefulBeanToCsvBuilder中使用此自定义策略,与第一个解决方案完全相同(请记住调用mappingStrategy.setType(MappingsBean.class);否则此解决方案将无效).
目前,我们的MappingsBean必须包含CsvBindByName和CsvBindByPosition注释.第一个给出标题列名称,第二个用于在输出CSV标题中创建列的排序.现在,如果我们更改(使用注释)列名称或MappingsBean类中的排序 – 该更改将反映在输出CSV文件中.
标签:opencsv,java,csv,xml 来源: https://codeday.me/bug/20190926/1822265.html