代码之家  ›  专栏  ›  技术社区  ›  Bishan

带列标题的StatefulBeanToCsv

  •  15
  • Bishan  · 技术社区  · 8 年前

    我正在使用 opencsv-4.0

    这是我的密码。

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

    上面的代码创建了一个包含数据的csv文件。但它不包括该文件中的列标题。

    5 回复  |  直到 8 年前
        1
  •  21
  •   Community Mohan Dere    6 年前

    ColumnPositionMappingStrategy#generateHeader返回空数组

    /**
     * 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];
    }
    

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

    它将产品的类成员写入CSV头

    如果您的产品类成员名称为

    "productCode", "MFD", "EXD"
    

    这应该是正确的解决方案

    否则,添加@CsvBindByName注释

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

    “EXD”、“MFD”、“PRODUCTCODE”

    "333","33","3"

        2
  •  8
  •   Bruno Muehlbauer de Souza    6 年前

    public void export(List<YourObject> list, PrintWriter writer) throws Exception {
            writer.append( buildHeader( YourObject.class ) );
            StatefulBeanToCsvBuilder<YourObject> builder = new StatefulBeanToCsvBuilder<>( writer );
            StatefulBeanToCsv<YourObject> beanWriter = builder.build();
            beanWriter.write( mapper.map( list ) );
            writer.close();
        }
    
        private String buildHeader(Class<YourObject> clazz) {
            return Arrays.stream( clazz.getDeclaredFields() )
                    .filter( f -> f.getAnnotation( CsvBindByPosition.class ) != null
                            && f.getAnnotation( CsvBindByName.class ) != null )
                    .sorted( Comparator.comparing( f -> f.getAnnotation( CsvBindByPosition.class ).position() ) )
                    .map( f -> f.getAnnotation( CsvBindByName.class ).column() )
                    .collect( Collectors.joining( "," ) ) + "\n";
        }
    
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    public class YourObject {
    
        @CsvBindByPosition(position = 0)
        @CsvBindByName(column = "A")
        private Long a;
    
        @CsvBindByPosition(position = 1)
        @CsvBindByName(column = "B")
        private String b;
    
        @CsvBindByPosition(position = 2)
        @CsvBindByName(column = "C")
        private String c;
    
    }
    
        3
  •  5
  •   Ithar    8 年前

    我可能错过了一些明显的东西,但你不能将头字符串附加到writer对象吗?

    Writer writer = new FileWriter(filePath);
    writer.append("header1, header2, header3, ...etc \n");
    
    // This will be followed by your code with BeanToCsvBuilder 
    // Note: the terminating \n might differ pending env.
    
        4
  •  0
  •   Yonas    5 年前

    来自的javadoc StatefulBeanToCsvBuilder.withMappingStrategy

    读取CSV源代码,从读取操作中获取映射策略,并将其传递给此方法进行写入操作是完全合法的。这节省了一些处理时间,但更重要的是,保留了标头顺序。

    这样,您将获得一个包含标题的CSV,其中列的顺序与原始CSV相同。

    使用OpenCSV 5.4为我工作。

        5
  •  -1
  •   Saravanakumar V    5 年前

    ColumnPositionMappingStrategy<Product> mappingStrategy = new ColumnPositionMappingStrategy<Product>() {
                @Override
                public String[] generateHeader(Product bean) throws CsvRequiredFieldEmptyException {
                    return this.getColumnMapping();
                }
            };