2011-11-27 41 views
2

@Carlo V. Dango 我簡化了我的問題,並且我已經閱讀了文檔 - 建議不要驚慌。不過,我有問題。幫我解決一個問題,它會解決所有問題。謝謝。解析SuperCSV字符串

問題:當我有一個缺少非字符串字段的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 

我的用戶豆:

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) 

感謝。

回答

1

列表閱讀器將每行讀入字符串列表。看來這是你正在尋找的。

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

或這裏http://supercsv.sourceforge.net/codeExamples_general.html所示,你可以設置處理器爲空,如果你不希望任何具體的實現。

+0

非常感謝您... – Davidson

+0

嗨...如果我有一個應該轉換爲BigDecimal的空白列,我試圖\t \t \t \t \t新ParseBigDecimal(新StrReplace(」」,‘0’)), – Davidson

+0

當建立cellprocessors,你從內到外或在外面搭建....例如..如果我有一個空白在一列,否則將是一個數量值,我如何鏈處理器將空白轉換爲0,然後使用ParseBigDecimal?我越來越絕望地理解我不理解的東西。意識到我可以在CellProcessor數組中放置一個空值是巨大的。我在網站的例子中解釋爲「閱讀但未處理」,完全忽略。 – Davidson

3

編輯:更新Super CSV 2.0.0-beta-1

超級CSV 2.0.0-β-1是現在出來。它包含許多錯誤修復和新功能(包括Maven支持和用於映射嵌套屬性和數組/集合的新Dozer擴展)。

它也改變了空("")列的處理方式 - 它們現在被讀爲null。 這意味着您的bean中的firstNamelastName字段現在將是null而不是""(如果它們不存在於CSV文件中)。

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五男子的CsvListReader是一個非常原始的實現(和你失去映射到豆的能力),所以我只用它來快速和骯髒的解析。

而且我只建議在數組中使用null(讀取時)獲取不需要進一步處理的字符串屬性。

順便說一句,我在爲即將發佈的超級CSV項目工作。我一定會在網頁上改進代碼示例;)

+0

非常感謝您提供這個建議。在我原來的問題的實例中,我走了製作bean中所有字段字符串的路線,並在我的過程中稍後解析它們。我將採用這個示例,並使用我必須使用的輸入文件對它進行測試。我一直認爲我的問題是我自己在鏈接單元處理器方面的笨拙。我愛豆閱讀器/作家。我們公司正在轉型爲SAP,它有許多讀/寫所有定製界面的CSV文件的機會。 SuperCSV是我們現在處理中的重要參與者。 – Davidson

+1

@Davidson很高興聽到您仍在使用Super CSV,這是一個非常棒的小API。它已經休眠了一段時間,但我最近加入了這個項目,希望能爲它注入新的活力。如果您有任何關於新功能的問題或想法,請發佈在Super CSV SourceForge論壇上 - 我們很樂意聽取您的意見。你很幸運,你與SAP的接口是CSV,在我的工作中它是位置的(第一列是20個字符,第二個是10個字符等)!順便說一下,如果你覺得這有幫助,你可以投票/選擇這個答案? –