【问题标题】:How to write List<String> to csv file & read it back using supercsv如何将 List<String> 写入 csv 文件并使用 supercsv 读回
【发布时间】:2014-01-15 18:26:14
【问题描述】:

我正在使用 supercsv CsvBeanWriter 将值写入 csv 文件。

示例类:

public class Employee {
    private String name;

    private int empId;

    List<String> phoneNumbers;
}

我得到的输出是:

name,empId,phoneNumbers
vijay,1,"[123, 456]"

注意List&lt;String&gt; phoneNumbers 是如何写在[] 中的

我的问题是如何使用 supercsv 将其读回 Employee 类(bean)。

我尝试使用CsvBeanReaderCsvDozerBeanReader,但无法读取List&lt;String&gt;

我得到了非法参数异常。 将感谢任何指针!

完整代码:

public class DozerBeanReader {
public static void main(String [] args){
    ICsvDozerBeanReader beanReader = null;

    try {
        beanReader = new CsvDozerBeanReader(new FileReader("Employee.csv"), 
                CsvPreference.STANDARD_PREFERENCE);

        String [] header = beanReader.getHeader(true); // ignore the header

        Class<?> [] hintTypes = {String.class, Integer.class, List.class};

        beanReader.configureBeanMapping(Employee.class, header, hintTypes);

        Employee readEmp1 = beanReader.read(Employee.class);
        readEmp1.toString();
    } catch (FileNotFoundException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}
}

【问题讨论】:

    标签: java csv supercsv


    【解决方案1】:

    您依赖的事实是,您的电话号码 List 使用列表的 toString() 格式写入单个 CSV 列,例如[123, 456]

    您将收到类似以下内容的异常:

    org.dozer.MappingException: Illegal object type 
    for the method 'setPhoneNumbers'. 
    Expected types: 
    java.util.List
    Actual types: 
    java.lang.String
    

    因为 Dozer 不知道如何将字符串 [123, 456] 转换为 List。您可以执行此操作,但您需要编写cell processor 以将该字符串转换回List。如果您的电话号码是纯数字,那应该不会太难,但如果您的电话号码有逗号,那么事情就会变得一团糟!

    我建议将每个电话号码写成一个单独的列 - 这样会更容易(对于任何阅读您文件的人,包括您!)。

    您需要做的就是将 CsvDozerBeanReader 和 CsvDozerBeanWriter 与 indexed mapping 一起使用。

    这是一个例子 - 关键部分是索引映射:

    String[] fieldMapping = new String[] { "name",
        "empId", "phoneNumbers[0]", "phoneNumbers[1]" };
    
    • 我已经定义了 2 个电话号码列 - 如果您的列表会有更多,那么只需添加更多列
    • 我本可以使用 fieldMapping 作为标题,但选择使用更具可读性的自定义标题
    • 您不应该需要问题中的提示
    • 我使用 StringReader/StringWriter 只是为了简化示例

    例子:

    // create employee to write/read
    Employee employee = new Employee();
    employee.setEmpId(1234);
    employee.setName("Vijay");
    employee.setPhoneNumbers(Arrays.asList("123", "456"));
    
    // the CSV header
    String[] header = new String[] { "name",
        "empId", "phoneNumber1", "phoneNumber2" };
    
    // the field mapping
    String[] fieldMapping = new String[] { "name",
        "empId", "phoneNumbers[0]", "phoneNumbers[1]" };
    
    // write the employee
    StringWriter out = new StringWriter();
    ICsvDozerBeanWriter writer = 
        new CsvDozerBeanWriter(out,
        CsvPreference.STANDARD_PREFERENCE);
    writer.configureBeanMapping(Employee.class, fieldMapping);
    writer.writeHeader(header);
    writer.write(employee);
    writer.flush();
    
    // read the employee
    ICsvDozerBeanReader reader = 
        new CsvDozerBeanReader(new StringReader(out.toString()),
        CsvPreference.STANDARD_PREFERENCE);
    reader.configureBeanMapping(Employee.class, fieldMapping);
    reader.getHeader(true); // ignore header
    Employee e = reader.read(Employee.class);
    System.out.println(e);
    

    假设您已经编写了 toString() 方法,应该会打印出来

    Employee [name=Vijay, empId=1234, phoneNumbers=[123, 456]]
    

    【讨论】:

    • 当我不知道 List 中有多少元素时,知道如何设置 String [] fieldMapping 吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-20
    • 2013-07-01
    • 2020-06-21
    相关资源
    最近更新 更多