2014-01-17 50 views
2

我有一個.tsv文件,它有39列 最後一列有數據作爲字符串,其長度超過100,000個字符 現在發生了什麼是當我試圖閱讀文件1號線有頭,然後將數據如下在讀取.tsv文件時跳過交替行

正在發生的事情是它的後讀線1的進入第3行,那麼第5,那麼第7 儘管所有的行具有相同的數據 繼日誌我得到

lineNo=3, rowNo=2, customer=503837-100 , last but one cell length=111275 
lineNo=5, rowNo=3, customer=503837-100 , last but one cell length=111275 
lineNo=7, rowNo=4, customer=503837-100 , last but one cell length=111275 
lineNo=9, rowNo=5, customer=503837-100 , last but one cell length=111275 
lineNo=11, rowNo=6, customer=503837-100 , last but one cell length=111275 
lineNo=13, rowNo=7, customer=503837-100 , last but one cell length=111275 
lineNo=15, rowNo=8, customer=503837-100 , last but one cell length=111275 
lineNo=17, rowNo=9, customer=503837-100 , last but one cell length=111275 
lineNo=19, rowNo=10, customer=503837-100 , last but one cell length=111275 

以下是m而Y碼:

import java.io.FileReader; 
import org.supercsv.cellprocessor.Optional; 
import org.supercsv.cellprocessor.constraint.NotNull; 
import org.supercsv.cellprocessor.ift.CellProcessor; 
import org.supercsv.io.CsvBeanReader; 
import org.supercsv.io.ICsvBeanReader; 
import org.supercsv.prefs.CsvPreference; 

public class readWithCsvBeanReader { 
    public static void main(String[] args) throws Exception{ 
     readWithCsvBeanReader(); 
    } 


private static void readWithCsvBeanReader() throws Exception { 

    ICsvBeanReader beanReader = null; 

    try { 

     beanReader = new CsvBeanReader(new FileReader("C:\MAP TSV\abc.tsv"), CsvPreference.TAB_PREFERENCE); 
     // the header elements are used to map the values to the bean (names must match) 
     final String[] header = beanReader.getHeader(true); 
     final CellProcessor[] processors = getProcessors(); 
     TSVReaderBrandDTO tsvReaderBrandDTO = new TSVReaderBrandDTO(); 

     int i = 0; 
     int last = 0; 

     while((tsvReaderBrandDTO = beanReader.read(TSVReaderBrandDTO.class, header, processors)) != null) { 
      if(null == tsvReaderBrandDTO.getPage_cache()){ 
       last = 0; 
      } 
      else{ 
       last = tsvReaderBrandDTO.getPage_cache().length(); 
      } 
      System.out.println(String.format("lineNo=%s, rowNo=%s, customer=%s , last but one cell length=%s", beanReader.getLineNumber(), 
       beanReader.getRowNumber(), tsvReaderBrandDTO.getUnique_ID(), last)); 
      i++; 
     } 

     System.out.println("Number of rows : "+i); 

    } 
    finally { 
     if(beanReader != null) { 
      beanReader.close(); 
     } 
    } 
} 

private static CellProcessor[] getProcessors() { 

    final CellProcessor[] processors = new CellProcessor[] { 
     new Optional(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new NotNull(), new NotNull(), 
     new NotNull(), new NotNull(), new NotNull(), new Optional()}; 

     return processors; 
    } 
} 

請讓我知道我錯了

回答

0

我檢查http://supercsv.sourceforge.net/examples_reading.html。仔細查看示例CSV文件輸出。難道不是你的行包含非轉義的"(雙撇號)字符,所以解析器認爲數據記錄跨越兩條物理線?

如果不使用雙撇號字符作爲引號字符,你可以改變CsvPreference - 見http://supercsv.sourceforge.net/apidocs/org/supercsv/prefs/CsvPreference.html - 使雙引號不被視爲一個引號字符:

CsvPreference MY_PREFERENCES = new CsvPreference.Builder(
    SOME_NEVER_USED_CHARACTER, ',', "\r\n").build(); 

當然對於製表符分隔CSV使用這樣的事情:

CsvPreference MY_PREFERENCES = new CsvPreference.Builder(
    SOME_NEVER_USED_CHARACTER, '\t', "\r\n").build(); 

參考CsvPreference的javadoc Builder的簽名,並相應修改的實際值。

+0

Ya Honza你說得對,它有一個非轉義的「...你能建議任何方法來處理它在運行時? –

+0

恐怕你應該: - 要麼處理它的應用程序數據 - 或者通過一個「預處理器」傳遞你的輸入文件 - 你的代碼讀取它並用兩個雙撇號替換所有的雙撇號。也許庫提供這樣的選項。 否則你的源文件不是一個有效的CSV/TSV。 順便說一句,如果我回答了你的問題,並且存在非轉義雙撇號是你問題的根源,那麼你能否將我的答案標記爲答案? :) 謝謝。 –

+0

我所擁有的數據文件可能會有這些差異,問題是數據量很大,可能會在單個文件中達到100GB的數據......所以我無法設計處理器,因爲它會耗盡內存,我無法找到一種方法來處理這個問題,同時閱讀 –

0

如果您使用CSV解析器來解析TSV輸入,那麼您的時間將會很糟糕。 使用適當的TSV解析器。 uniVocity-parsers附帶TSV解析器/寫入器。您也可以使用帶註釋的Java Bean來將文件直接解析到類的實例中。

實例:

此代碼解析TSV爲行。

TsvParserSettings settings = new TsvParserSettings(); 

// creates a TSV parser 
TsvParser parser = new TsvParser(settings); 

// parses all rows in one go. 
List<String[]> allRows = parser.parseAll(new FileReader(yourFile)); 

使用BeanListProcessor解析到Java豆類:

BeanListProcessor<TestBean> rowProcessor = new BeanListProcessor<TestBean>(TestBean.class); 

TsvParserSettings parserSettings = new TsvParserSettings(); 
parserSettings.setRowProcessor(rowProcessor); 

TsvParser parser = new TsvParser(parserSettings); 
parser.parse(new FileReader(yourFile)); 

// The BeanListProcessor provides a list of objects extracted from the input. 
List<TestBean> beans = rowProcessor.getBeans(); 

這是中,testBean類的樣子: 類testBean這個{

// if the value parsed in the quantity column is "?" or "-", it will be replaced by null. 
@NullString(nulls = { "?", "-" }) 
// if a value resolves to null, it will be converted to the String "0". 
@Parsed(defaultNullRead = "0") 
private Integer quantity; 


@Trim 
@LowerCase 
@Parsed(index = 4) 
private String comments; 

// you can also explicitly give the name of a column in the file. 
@Parsed(field = "amount") 
private BigDecimal amount; 

@Trim 
@LowerCase 
// values "no", "n" and "null" will be converted to false; values "yes" and "y" will be converted to true 
@BooleanString(falseStrings = { "no", "n", "null" }, trueStrings = { "yes", "y" }) 
@Parsed 
private Boolean pending; 

披露:我是這個作者圖書館。它是開放源代碼和免費的(Apache V2.0許可證)。

相關問題