@Carlo V. Dango 我已经简化了我的问题,并且已经阅读了文档——好的建议,不要 panic 。不过,我还是有问题。帮我解决一个,就能解决所有问题。谢谢。
问题:当我的 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)
谢谢。
最佳答案
编辑: Super CSV 2.0.0-beta-1 的更新
Super CSV 2.0.0-beta-1 现已发布。它包括许多错误修复和新功能(包括 Maven 支持和用于映射嵌套属性和数组/集合的新 Dozer 扩展)。
它还改变了处理空 (""
) 列的方式 - 它们现在被读取为 null
。
这意味着 bean 中的 firstName
和 lastName
字段现在将为 null
而不是 ""
(如果它们是)不存在于 CSV 文件中。
Optional()
处理器已更新以满足此需求 - 因此它仍将以相同的方式运行。
我关于使用Token
的建议不再相关:您应该使用ConvertNullTo
:
new ConvertNullTo(-1, new ParseInt())
您真正想要的是可选
CellProcessor,它仅在列不为空时才允许链中的下一个处理器执行。
因此将您的 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
处理器,该处理器会将任何标记(本例中为“”)替换为所需值,对于任何其他输入,它将继续到下一个处理器。即
new Token("", -1, new ParseInt())
@Carlo V. Dango,CsvListReader 是一个非常原始的实现(并且您失去了映射到 beans 的能力),因此我只将它用于快速和肮脏的解析。
对于不需要进一步处理的字符串属性,我只建议在数组(读取时)中使用 null
。
顺便说一句,我正在参与 Super CSV 项目,致力于即将发布的版本。我一定会改进网站上的代码示例;)
关于java - 解析 SuperCSV 中的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8289855/