OpenCsv使用BeanToCsv+HeaderColumnNameTranslateMappingStrategy写



我使用opencsv 3.6来创建一个从javabean开始的csv文件。

首先,我尝试了这个代码:

import com.opencsv.CSVReader;
import com.opencsv.CSVWriter;
import com.opencsv.bean.BeanToCsv;
import com.opencsv.bean.HeaderColumnNameTranslateMappingStrategy;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class CustomBean {
    private String name;
    private String surname;
    public CustomBean(String n, String s) {
        this.name = n;
        this.surname = s;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setSurname(String surname) {
        this.surname = surname;
    }
    public String getSurname() {
        return surname;
    }
    public static void main(String[] args) {
        Map<String,String> mapping = new HashMap<String,String>();
        mapping.put("COLUMN1","name");
        mapping.put("COLUMN2","surname");
        HeaderColumnNameTranslateMappingStrategy<CustomBean> strategy = new HeaderColumnNameTranslateMappingStrategy<CustomBean>();
        strategy.setType(CustomBean.class);
        strategy.setColumnMapping(mapping);
        ArrayList<CustomBean> customUsers = new ArrayList<CustomBean>();
        customUsers.add(new CustomBean("Kobe","Bryant"));
        BeanToCsv<CustomBean> bean = new BeanToCsv<CustomBean>();
        try {            
            CSVWriter writer = new CSVWriter(new FileWriter("testOut.csv"));
            bean.write(strategy, writer, customUsers);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

但我有以下错误:

Exception in thread "main" java.lang.RuntimeException: Error writing CSV !
    at com.opencsv.bean.BeanToCsv.write(BeanToCsv.java:74)
    at test.CustomBean.main(CustomBean.java:63)
Caused by: java.lang.NullPointerException
    at com.opencsv.bean.HeaderColumnNameTranslateMappingStrategy.getColumnName(HeaderColumnNameTranslateMappingStrategy.java:45)
    at com.opencsv.bean.HeaderColumnNameMappingStrategy.findDescriptor(HeaderColumnNameMappingStrategy.java:112)
    at com.opencsv.bean.BeanToCsv.processHeader(BeanToCsv.java:103)
    at com.opencsv.bean.BeanToCsv.write(BeanToCsv.java:69)
    ... 1 more

发生这种情况是因为在HeaderColumnNameTranslateMappingStrategy类的getColumnName方法中的opencsv源代码中有以下行:

return col < header.length ? columnMapping.get(header[col].toUpperCase()) : null;

因此,header为空。这是真的,事实上这个类是HeaderColumnNameMappingStrategy类的一个子类,它包含从未初始化的header变量(String[]类型)。

我在这个类中找到的唯一有用的方法是captureHeader,但不幸的是,它需要一个CSVReader作为输入。

出于这个原因,我创建了一个空的csv文件:

COLUMN1,COLUMN2

我在try/catch块的开头添加了以下几行:

CSVReader reader = new CSVReader(new FileReader("testIn.csv"));
strategy.captureHeader(reader);

这样(我真的不喜欢,因为我必须创建一个csv文件)我也不例外,但在结果csv文件中,列的名称不遵循映射策略:

"name","surname"
"Kobe","Bryant"

两个问题:

  1. 如何获得预期的结果,即csv文件中的正确列名
  2. 有没有办法不使用CSVReader

查看BeanToCsv的源代码,processHeader(...)方法对所提供的标头不执行任何操作。您唯一的选择是创建一个自定义策略(以避免CSVReader)和一个自定义BeanToCsv,如下所示


public class CustomBean {
   ...
   public static void main(String[] args) {
     ...
     HeaderColumnNameTranslateMappingStrategy strategy = new CustomStrategy<CustomBean>();
     strategy.setType(CustomBean.class);
     strategy.setColumnMapping(mapping);
     ...
     BeanToCsv bean = new CustomBeanToCsv<CustomBean>();
     ...
   }
   static class CustomStrategy<T> extends HeaderColumnNameTranslateMappingStrategy {
    @Override
    public void setColumnMapping(Map columnMapping) {
        super.setColumnMapping(columnMapping);
        header = new String[columnMapping.size()];
        int i = 0;
        for (Map.Entry entry : columnMapping.entrySet()) {
            header[i] = entry.getKey().toUpperCase();
            i++;
        }
    }
     public String[] getHeader() {
         return header;
     }
   }
   static class CustomBeanToCsv<T> extends BeanToCsv {
     @Override
     protected String[] processHeader(MappingStrategy mapper) throws IntrospectionException {
         if (mapper instanceof CustomStrategy) {
             return ((CustomStrategy) mapper).getHeader();
         } else {
             return super.processHeader(mapper);
         }
     }
   }
}
 

我已经使用openCSV五年了,我仍在学习有关它的知识。问题是HeaderColumnNameMappingStrategy和HeaderColumnNameTranslateMappingStrategy是为CsvToBean制作的。它希望读取一个文件以获取标头,从而查看读取器应该从何处读取。

对于BeanToCsv类,请使用ColumnPositionMappingStrategy类。你给它一个你正在映射的类和一个你想映射的列的列表,它为你完成剩下的工作。

这是我写的一个有效的小测试方法。

public void createUsingBeanToCsv(int numRecords, FileWriter fos) {
    List<SmallRecord> smallRecords = new ArrayList<>(numRecords);
    for (int i = 0; i < numRecords; i++) {
        smallRecords.add(SmallRecordGenerator.createRecord(i));
    }
    BeanToCsv<SmallRecord> beanToCsv = new BeanToCsv<>();
    ColumnPositionMappingStrategy<SmallRecord> strategy = new ColumnPositionMappingStrategy<>();
    strategy.setType(SmallRecord.class);
    String[] columns = new String[]{"bigDecimal_1", "name_1", "intNumber_1"};
    strategy.setColumnMapping(columns);
    beanToCsv.write(strategy, fos, smallRecords);
}

相关内容

  • 没有找到相关文章

最新更新