OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件? [英] OpenCSV: How to create CSV file from POJO with custom column headers and custom column positions?

查看:599
本文介绍了OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个MappingsBean类,其中指定了CSV文件的所有列。接下来,我解析XML文件并创建mappingbeans列表。然后我将该数据写入CSV文件作为报告。

I have created a MappingsBean class where all the columns of the CSV file are specified. Next I parse XML files and create a list of mappingbeans. Then I write that data into CSV file as report.

我正在使用以下注释:

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文件的类:

And then I use StatefulBeanToCsv class to write into CSV file:

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),那么我无法设置列的位置。

The problem with this approach is that if I use @CsvBindByPosition(position = 0) to control position then I am not able to generate column names. If I use @CsvBindByName(column = "TradeID") then I am not able to set position of the columns.

有没有办法可以同时使用两个注释,这样我就可以创建带有列标题的CSV文件并控制列位置?

Is there a way where I can use both annotations, so that I can create CSV files with column headers and also control column position?

问候,
Vikram Pathania

Regards, Vikram Pathania

推荐答案

我'我有类似的问题。 AFAIK OpenCSV中没有内置功能,允许使用自定义列名排序将bean写入CSV。

I've had similar problem. AFAIK there is no build-in functionality in OpenCSV that will allow to write bean to CSV with custom column names and ordering.

开箱即用的OpenCSV中有两个主要的 MappingStrategy

There are two main MappingStrategyies that are available in OpenCSV out of the box:


  • HeaderColumnNameMappingStrategy :允许根据自定义名称将CVS文件列映射到bean字段;将bean写入CSV时,这允许更改列标题名称,但我们无法控制列顺序

  • ColumnPositionMappingStrategy :允许映射基于列排序的CSV文件列到bean字段;将bean写入CSV时,我们可以控制列顺序,但是我们得到一个空头(实现返回 new String [0] 作为标题)

  • HeaderColumnNameMappingStrategy: that allows to map CVS file columns to bean fields based on custom name; when writing bean to CSV this allows to change column header name but we have no control on column order
  • ColumnPositionMappingStrategy: that allows to map CSV file columns to bean fields based on column ordering; when writing bean to CSV we can control column order but we get an empty header (implementation returns new String[0] as a header)

我发现实现自定义列名和排序的唯一方法是编写自定义 MappingStrategy

The only way I found to achieve both custom column names and ordering is to write your custom 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文件中。

In MappingsBean class we left CsvBindByPosition annotations - to control ordering (in this solution CsvBindByName annotations are not needed). Thanks to custom mapping strategy the header column names are included in resulting CSV file.

此解决方案的缺点是当我们通过更改列排序时CsvBindByPosition 注释我们必须在自定义映射策略中手动更改 HEADER 常量。

The downside of this solution is that when we change column ordering through CsvBindByPosition annotation we have to manually change also HEADER constant in our custom mapping strategy.

第一种解决方案有效,但对我来说并不好。基于 MappingStrategy 的内置实现,我提出了另一个实现:

The first solution works, but it was not good for me. Based on build-in implementations of MappingStrategy I came up with yet another implementation:

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();
    }
}

您可以在<$ c $中使用此自定义策略c> StatefulBeanToCsvBuilder 与第一个解决方案完全相同(记得调用 mappingStrategy.setType(MappingsBean.class); ,否则此解决方案不会工作)。

You can use this custom strategy in StatefulBeanToCsvBuilder exactly this same as in the first solution (remember to invoke mappingStrategy.setType(MappingsBean.class);, otherwise this solution will not work).

目前我们的 MappingsBean 必须包含 CsvBindByName CsvBindByPosition 注释。第一个给出标题列名称,第二个用于在输出CSV标题中创建列的排序。现在,如果我们更改(使用注释)列名或 MappingsBean 类中的顺序 - 该更改将反映在输出CSV文件中。

Currently our MappingsBean has to contain both CsvBindByName and CsvBindByPosition annotations. The first to give header column name and the second to create ordering of columns in the output CSV header. Now if we change (using annotations) either column name or ordering in MappingsBean class - that change will be reflected in output CSV file.

这篇关于OpenCSV:如何使用自定义列标题和自定义列位置从POJO创建CSV文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆