Search code examples
javacsvopencsv

StatefulBeanToCsv with Column headers


I am using opencsv-4.0 to write a csv file and I need to add column headers in output file.

Here is my code.

public static void buildProductCsv(final List<Product> product,
        final String filePath) {

    try {

        Writer writer = new FileWriter(filePath);

        // mapping of columns with their positions
        ColumnPositionMappingStrategy<Product> mappingStrategy = new ColumnPositionMappingStrategy<Product>();
        // Set mappingStrategy type to Product Type
        mappingStrategy.setType(Product.class);
        // Fields in Product Bean
        String[] columns = new String[] { "productCode", "MFD", "EXD" };
        // Setting the colums for mappingStrategy
        mappingStrategy.setColumnMapping(columns);

        StatefulBeanToCsvBuilder<Product> builder = new StatefulBeanToCsvBuilder<Product>(writer);

        StatefulBeanToCsv<Product> beanWriter = builder.withMappingStrategy(mappingStrategy).build();
        // Writing data to csv file
        beanWriter.write(product);
        writer.close();

        log.info("Your csv file has been generated!");

    } catch (Exception ex) {
        log.warning("Exception: " + ex.getMessage());
    }

}

Above code create a csv file with data. But it not include column headers in that file.

How could I add column headers to output csv?


Solution

  • ColumnPositionMappingStrategy#generateHeader returns empty array

    /**
     * This method returns an empty array.
     * The column position mapping strategy assumes that there is no header, and
     * thus it also does not write one, accordingly.
     * @return An empty array
     */
    @Override
    public String[] generateHeader() {
        return new String[0];
    }
    

    If you remove MappingStrategy from BeanToCsv builder

    // replace 
    StatefulBeanToCsv<Product> beanWriter = builder.withMappingStrategy(mappingStrategy).build();
    // with
    StatefulBeanToCsv<Product> beanWriter = builder.build(); 
    

    It will write Product's class members as CSV header

    If your Product class members names are

    "productCode", "MFD", "EXD"
    

    This should be the right solution

    Else, add @CsvBindByName annotation

    import com.opencsv.bean.CsvBindByName;
    import com.opencsv.bean.StatefulBeanToCsv;
    import com.opencsv.bean.StatefulBeanToCsvBuilder;
    
    import java.io.FileWriter;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.List;
    
    public class CsvTest {
    
        public static void main(String[] args) throws Exception {
            Writer writer = new FileWriter(fileName);
    
            StatefulBeanToCsvBuilder<Product> builder = new StatefulBeanToCsvBuilder<>(writer);
            StatefulBeanToCsv<Product> beanWriter = builder.build();
    
            List<Product> products = new ArrayList<>();
            products.add(new Product("1", "11", "111"));
            products.add(new Product("2", "22", "222"));
            products.add(new Product("3", "33", "333"));
            beanWriter.write(products);
            writer.close();
        }
    
        public static class Product {
            @CsvBindByName(column = "productCode")
            String id;
            @CsvBindByName(column = "MFD")
            String member2;
            @CsvBindByName(column = "EXD")
            String member3;
    
            Product(String id, String member2, String member3) {
                this.id = id;
                this.member2 = member2;
                this.member3 = member3;
            }
    
            public String getId() {
                return id;
            }
    
            public void setId(String id) {
                this.id = id;
            }
    
            public String getMember2() {
                return member2;
            }
    
            public void setMember2(String member2) {
                this.member2 = member2;
            }
    
            public String getMember3() {
                return member3;
            }
    
            public void setMember3(String member3) {
                this.member3 = member3;
            }
        }
    
    }
    

    Output:

    "EXD","MFD","PRODUCTCODE"

    "111","11","1"

    "222","22","2"

    "333","33","3"

    Pay attention; class, getters & setters needs to be public due to the use of Reflection by OpenCSV library