解析SuperCSV中的字符串

时间:2011-11-27 23:09:16

标签: java csv supercsv

@Carlo V. Dango 我已经简化了我的问题,我已经阅读了文档 - 不要惊慌的好建议。不过,我有问题。帮助我解决一个,它将解决所有问题。谢谢。

问题:当我有一个缺少非String字段的csv记录时,如何(甚至可以)将缺失的条目转换为默认值,或者至少不抛出NullPointerException?可选的cellProcessor似乎也不会阻止错误。

该计划主要来自SuperCSV网站。

package com.test.csv;
import java.io.FileReader;

import org.supercsv.cellprocessor.ParseBigDecimal;
import org.supercsv.cellprocessor.ParseDate;
import org.supercsv.cellprocessor.ParseInt;
import org.supercsv.cellprocessor.ift.CellProcessor;
import org.supercsv.io.CsvBeanReader;
import org.supercsv.io.ICsvBeanReader;
import org.supercsv.prefs.CsvPreference;


public class CSVReader {

private static final CellProcessor[] cellProcessor = new CellProcessor[] {
    null,
    null,
    new ParseInt(),
    new ParseDate("yyyyMMdd"),      
    new ParseBigDecimal()       
};

public static void main (String[] args ) throws Exception {

    CsvPreference pref = new CsvPreference('"', '|', "\n");

    ICsvBeanReader inFile = new CsvBeanReader(new FileReader("C:\\temp\\sapfilePipe.txt"), pref);
    try {
        final String[] header = inFile.getCSVHeader(true);
        User user;
        while ((user = inFile.read(User.class, header, cellProcessor)) != null) {
            System.out.println(user);
        }
    } finally {
        inFile.close();
    }

}

}

这是我正在阅读的CSV文件。请注意,在第一条记录中有一个缺失的字段(年龄)。

firstName|lastName|age|hireDate|hourlyRate
A.|Smith|  |20110101|15.50

我的用户bean:

package com.test.csv;

import java.math.BigDecimal;
import java.util.Date;

public class User {

private String firstName;
private String lastName;
private int age;
private Date hireDate;
private BigDecimal hourlyRate;
    ...getters/setters...   

这是错误:

Exception in thread "main" java.lang.NullPointerException
    at org.supercsv.io.CsvBeanReader.fillObject(Unknown Source)
    at org.supercsv.io.CsvBeanReader.read(Unknown Source)
    at com.glazers.csv.CSVReader.main(CSVReader.java:31)

感谢。

2 个答案:

答案 0 :(得分:3)

修改:[{3}}

的更新

Super CSV 2.0.0-beta-1现已推出。它包含许多错误修复和新功能(包括Maven支持和用于映射嵌套属性和数组/集合的新Dozer扩展)。

它还改变了处理空("")列的方式 - 它们现在被读作null。 这意味着,如果CSV文件中不存在,则bean中的firstNamelastName字段现在将为null而不是""

Optional()处理器已更新以满足此要求 - 因此它仍将以相同的方式运行。

我建议使用Token不再相关:您应该使用ConvertNullTo代替:

new ConvertNullTo(-1, new ParseInt())

真正想要的是Optional CellProcessor,如果列不为空,它只允许链中的下一个处理器执行。

因此,将CellProcessor数组更新为:

private static final CellProcessor[] cellProcessor = new CellProcessor[] {
    null,
    null,
    new Optional(new ParseInt()),
    new ParseDate("yyyyMMdd"),      
    new ParseBigDecimal()       
};

这样,只有当列不为空(CellProcessors从左到右执行)时才会执行ParseInt,将bean中的int字段保留为默认值0。

如果要将字段设置为-1表示没有提供任何值,则可以使用Token处理器,它将使用所需值替换任何令牌(在本例中为“”),对于任何其他输入,它将继续到下一个处理器。即。

new Token("", -1, new ParseInt())

@Carlo V. Dango CsvListReader是一个非常原始的实现(并且你失去了映射到bean的能力)所以我只会用它来进行快速和脏的解析。

我只建议在数组中使用null(在阅读时),不需要进一步处理的字符串属性。

顺便说一下,我正在为即将发布的版本工作的Super CSV项目。我一定会在网站上改进代码示例;)

答案 1 :(得分:1)

列表阅读器将每一行读入字符串列表。看来这就是你要找的东西。

http://supercsv.sourceforge.net/javadoc/org/supercsv/io/CsvListReader.html

或如此处所示http://supercsv.sourceforge.net/codeExamples_general.html如果您不想要任何具体的操作,可以将处理器设置为null。