OpenCSV: How to create CSV file from POJO with custom column headers and custom column positions?

后端 未结 19 1456
温柔的废话
温柔的废话 2020-12-08 04:14

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 int

19条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-08 05:08

    I've improved on previous answers by removing all references to deprecated APIs while using the latest release of opencsv (4.6).

    A Generic Kotlin Solution

    /**
     * Custom OpenCSV [ColumnPositionMappingStrategy] that allows for a header line to be generated from a target CSV
     * bean model class using the following annotations when present:
     * * [CsvBindByName]
     * * [CsvCustomBindByName]
     */
    class CustomMappingStrategy(private val beanType: Class) : ColumnPositionMappingStrategy() {
        init {
            setType(beanType)
            setColumnMapping(*getAnnotatedFields().map { it.extractHeaderName() }.toTypedArray())
        }
    
        override fun generateHeader(bean: T): Array = columnMapping
    
        private fun getAnnotatedFields() = beanType.declaredFields.filter { it.isAnnotatedByName() }.toList()
    
        private fun Field.isAnnotatedByName() = isAnnotationPresent(CsvBindByName::class.java) || isAnnotationPresent(CsvCustomBindByName::class.java)
    
        private fun Field.extractHeaderName() =
            getAnnotation(CsvBindByName::class.java)?.column ?: getAnnotation(CsvCustomBindByName::class.java)?.column ?: EMPTY
    }
    

    Then use it as follows:

    private fun csvBuilder(writer: Writer) =
        StatefulBeanToCsvBuilder(writer)
            .withSeparator(ICSVWriter.DEFAULT_SEPARATOR)
            .withMappingStrategy(CustomMappingStrategy(MappingsBean::class.java))
            .withApplyQuotesToAll(false)
            .build()
    
    // Kotlin try-with-resources construct
    PrintWriter(File("$reportOutputDir/$REPORT_FILENAME")).use { writer ->
        csvBuilder(writer).write(makeFinalMappingBeanList())
    }
    

    and for completeness, here's the CSV bean as a Kotlin data class:

    data class MappingsBean(
        @field:CsvBindByName(column = "TradeID")
        @field:CsvBindByPosition(position = 0, required = true)
        private val tradeId: String,
    
        @field:CsvBindByName(column = "GWML GUID", required = true)
        @field:CsvBindByPosition(position = 1)
        private val gwmlGUID: String,
    
        @field:CsvBindByName(column = "MXML GUID", required = true)
        @field:CsvBindByPosition(position = 2)
        private val mxmlGUID: String,
    
        @field:CsvBindByName(column = "GWML File")
        @field:CsvBindByPosition(position = 3)
        private val gwmlFile: String? = null,
    
        @field:CsvBindByName(column = "MxML File")
        @field:CsvBindByPosition(position = 4)
        private val mxmlFile: String? = null,
    
        @field:CsvBindByName(column = "MxML Counterparty")
        @field:CsvBindByPosition(position = 5)
        private val mxmlCounterParty: String? = null,
    
        @field:CsvBindByName(column = "GWML Counterparty")
        @field:CsvBindByPosition(position = 6)
        private val gwmlCounterParty: String? = null
    )
    

提交回复
热议问题