【问题标题】:Parsing Strings in SuperCSV在 SuperCSV 中解析字符串
【发布时间】:2012-01-07 13:24:28
【问题描述】:

@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)

谢谢。

【问题讨论】:

    标签: java csv supercsv


    【解决方案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。

    【讨论】:

    • 嗨...如果我有一个应该转换为 BigDecimal 的空白列,我尝试了 new ParseBigDecimal(new StrReplace(" ", "0")),
    • 在构建单元处理器时,您是从内向外构建还是从外向内构建......例如..如果我的列中有一个空白,否则它会是一个数量值,我该怎么做链处理器将空白转换为 0 然后使用 ParseBigDecimal?我越来越渴望理解我不理解的东西。意识到我可以在 CellProcessor 数组中放置一个 null 是巨大的。我将网站示例中的“已读但未处理”解释为完全“忽略”。
    • supercsv.sourceforge.net/codeExamples_general.html 所示,由外而内。这是具有独特处理器的第一个示例。尽量不要惊慌,而是专注于阅读文档。它的标题是“入门”,因此应该具有一定的相关性。
    【解决方案2】:

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

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

    它还改变了处理空 ("") 列的方式 - 现在它们被读取为 null。 这意味着如果 CSV 文件中不存在 firstNamelastName 字段,则 bean 中的字段现在将是 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()       
    };
    

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

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

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

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

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

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

    【讨论】:

    • 非常非常非常感谢您提供此提示。在我最初的问题的例子中,我在 bean 中创建了所有字段字符串,然后在我的过程中将它们解析出来。我将采用这个样本,并使用我必须使用的输入文件对其进行测试。我一直认为我的问题是我自己在链接单元处理器方面的笨拙。我喜欢豆类读者/作家。我们公司正在转换为 SAP,它有很多机会为所有自定义界面读取/写入 CSV 文件。 SuperCSV 现在是我们处理过程中的重要角色。
    • @Davidson 很高兴听到您仍在使用 Super CSV - 这是一个很棒的小 API。它已经休眠了一段时间,但我最近加入了这个项目,并希望为它注入一些新的活力。如果您对新功能有任何问题或想法,请在 Super CSV SourceForge 论坛上发帖 - 我们很乐意听取您的意见。你很幸运,你与 SAP 的接口是 CSV,在我的工作中它是位置的(第一列是 20 个字符,第二列是 10 个字符,等等)!顺便说一句,如果你觉得这有帮助,你能投票/选择这个答案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2011-06-20
    • 2010-10-11
    • 2017-10-12
    • 2011-07-03
    • 1970-01-01
    相关资源
    最近更新 更多