编程语言
首页 > 编程语言> > java – OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?

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