2

@Carlo V. Dango 我已经简化了我的问题,并且我已经阅读了文档——不要惊慌的好建议。不过,我还是有问题。帮我解决一个,它会解决所有问题。谢谢你。

问题:当我有一个缺少非字符串字段的 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)

谢谢。

4

2 回答 2

3

编辑:Super CSV 2.0.0-beta-1 的更新

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

它还改变了处理空 ( "") 列的方式 - 它们现在被读取为null. 这意味着如果 CSV 文件中不存在 bean 中的firstName和字段,则它们 lastName现在将null代替。""

Optional()处理器已经更新以适应这一点 - 所以它仍然会以相同的方式运行。

我的使用建议Token不再相关:您应该ConvertNullTo改用:

new ConvertNullTo(-1, new ParseInt())

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

因此,将您的 CellProcessor 数组更新为:

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

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

如果您想将该字段设置为 -1 以指示未提供任何值,那么您可以使用Token处理器,它将用所需值替换任何标记(在本例中为“”),对于任何其他输入,它将继续下一个处理器。IE

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

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

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

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

于 2012-02-12T12:59:36.820 回答
1

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

http://super-csv.github.io/super-csv/apidocs/org/supercsv/io/CsvListReader.html

或如这里所示http://super-csv.github.io/super-csv/examples_reading.html如果您不想做任何特定的事情,您可以将处理器设置为 null 。

于 2011-11-28T12:06:44.077 回答