2012-12-14 3 views
8

CSVTSV (Tab sepperated) 파일 약 1000000 행 이상을 읽으려고합니다. 이제 을 ~2500000 개의 줄이 포함 된 opencsv으로 읽으려고했으나 java.lang.NullPointerException이 표시됩니다. ~250000 개의 줄이있는 작은 파일 TSV과 함께 작동합니다. 그래서 큰 CSVTSV 파일을 읽을 수있는 다른 Libraries이 있는지 궁금합니다. 아이디어가 있습니까?Java 용 Good and effective CSV/TSV Reader

내 코드에 관심이

모두 (내가 그렇게 Try-Catch 분명히 잘못된, 그것을 단축) :

InputStreamReader in = null; 
CSVReader reader = null; 
try { 
    in = this.replaceBackSlashes(); 
    reader = new CSVReader(in, this.seperator, '\"', this.offset); 
    ret = reader.readAll(); 
} finally { 
    try { 
     reader.close(); 
    } 
} 

편집 :

private InputStreamReader replaceBackSlashes() throws Exception { 
     FileInputStream fis = null; 
     Scanner in = null; 
     try { 
      fis = new FileInputStream(this.csvFile); 
      in = new Scanner(fis, this.encoding); 
      ByteArrayOutputStream out = new ByteArrayOutputStream(); 

      while (in.hasNext()) { 
       String nextLine = in.nextLine().replace("\\", "/"); 
       // nextLine = nextLine.replaceAll(" ", ""); 
       nextLine = nextLine.replaceAll("'", ""); 
       out.write(nextLine.getBytes()); 
       out.write("\n".getBytes()); 
      } 

      return new InputStreamReader(new ByteArrayInputStream(out.toByteArray())); 
     } catch (Exception e) { 
      in.close(); 
      fis.close(); 
      this.logger.error("Problem at replaceBackSlashes", e); 
     } 
     throw new Exception(); 
    } 
+2

BufferedReader 덕분에 직접 읽지 않는 이유는 무엇입니까? –

+0

실제로 저는 잘 만들어진 코드와 공통적 인 코드를 원했고 휠을 재발 명하고 싶지 않았습니다. 실제로 모든 사람들이 생각하는 libs를 사용하고 있습니다. 그러나 아무런 효과가 없다면 그렇게 할 것입니다. – Robin

+2

그 많은 행을 나는 일괄 적으로 파일을 처리 할 것이다 : 파일에서 n 줄을 읽고 csv로 처리하고 다음 일괄 처리를 읽는다. – opi

답변

5

I :이 내가 InputStreamReader를 구성하는 방법입니다 그것을 시도하지 않았지만, 나는 superCSV를 더 일찍 조사했다.

http://sourceforge.net/projects/supercsv/

이 당신을 위해 작동하는 경우

http://supercsv.sourceforge.net/

확인

, 250 만 라인.

+0

감사합니다.이 라이브러리를 살펴 보겠습니다. – Robin

+0

고맙습니다. 'supercsv'는'2 500 000' 라인을 꽤 잘 처리합니다. – Robin

+2

@Robin Open CSV에 공평하기를 바란다면 최고 CSV 개발자로서 각 라인을 읽는 대신에'reader.readAll()'을 사용하면 (메모리) 문제가 발생할 것입니다. 그것으로 무언가를하는 것. 'replaceBackslashes()'메소드는 전체 파일을 메모리에 쓰는 동안 문제가 발생할 수도 있습니다. 스트림/독자 중 하나를 닫을 때 NPE가 발생 했습니까? –

1

Satish에서 제안한대로 전환 라이브러리를 사용해보세요. 도움이되지 않으면 전체 파일을 토큰으로 분할하여 처리해야합니다. 당신의 CSV 쉼표 그리고 당신이 그것을 처리 할 수 ​​

// r is the BufferedReader pointed at your file 
String line; 
StringBuilder file = new StringBuilder(); 
// load each line and append it to file. 
while ((line=r.readLine())!=null){ 
    file.append(line); 
} 
// Make them to an array 
String[] tokens = file.toString().split(","); 

에 대한 이스케이프 문자를 가지고 있지 않았다고 생각

. 토큰을 사용하기 전에 트리밍하는 것을 잊지 마십시오.

1

질문이 여전히 활성 상태인지는 모르겠지만 여기에 내가 성공적으로 사용하는 것이 있습니다. 그러나 스트림이나 반복 가능과 같은 더 많은 인터페이스를 구현해야 할 수도 있습니다.

import java.io.Closeable; 
import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.IOException; 
import java.io.InputStream; 
import java.util.Scanner; 

/** Reader for the tab separated values format (a basic table format without escapings or anything where the rows are separated by tabulators).**/ 
public class TSVReader implements Closeable 
{ 
    final Scanner in; 
    String peekLine = null; 

    public TSVReader(InputStream stream) throws FileNotFoundException 
    { 
     in = new Scanner(stream); 
    } 

    /**Constructs a new TSVReader which produces values scanned from the specified input stream.*/ 
    public TSVReader(File f) throws FileNotFoundException {in = new Scanner(f);} 

    public boolean hasNextTokens() 
    { 
     if(peekLine!=null) return true; 
     if(!in.hasNextLine()) {return false;} 
     String line = in.nextLine().trim(); 
     if(line.isEmpty()) {return hasNextTokens();} 
     this.peekLine = line;  
     return true;   
    } 

    public String[] nextTokens() 
    { 
     if(!hasNextTokens()) return null;  
     String[] tokens = peekLine.split("[\\s\t]+"); 
//  System.out.println(Arrays.toString(tokens)); 
     peekLine=null;  
     return tokens; 
    } 

    @Override public void close() throws IOException {in.close();} 
} 
+0

실제로 SuperCSV에 만족합니다. 자연스러운 구현 덕분에 – Robin

9

TSV 입력을 구문 분석하는 데 CSV 구문 분석기를 사용하지 마십시오. 예를 들어, TSV에 따옴표 문자가있는 필드가 있으면 중단됩니다.

uniVocity-parsers은 TSV 파서와 함께 제공됩니다. 문제없이 10 억 개의 행을 파싱 할 수 있습니다.

예는 TSV 입력을 구문 분석 :

TsvParserSettings settings = new TsvParserSettings(); 
TsvParser parser = new TsvParser(settings); 

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

사용자의 입력이 메모리에 저장 될 수없는 너무 큰 경우, 다음을 수행

TsvParserSettings settings = new TsvParserSettings(); 

// all rows parsed from your input will be sent to this processor 
ObjectRowProcessor rowProcessor = new ObjectRowProcessor() { 
    @Override 
    public void rowProcessed(Object[] row, ParsingContext context) { 
     //here is the row. Let's just print it. 
     System.out.println(Arrays.toString(row)); 
    } 
}; 
// the ObjectRowProcessor supports conversions from String to whatever you need: 
// converts values in columns 2 and 5 to BigDecimal 
rowProcessor.convertIndexes(Conversions.toBigDecimal()).set(2, 5); 

// converts the values in columns "Description" and "Model". Applies trim and to lowercase to the values in these columns. 
rowProcessor.convertFields(Conversions.trim(), Conversions.toLowerCase()).set("Description", "Model"); 

//configures to use the RowProcessor 
settings.setRowProcessor(rowProcessor); 

TsvParser parser = new TsvParser(settings); 
//parses everything. All rows will be pumped into your RowProcessor. 
parser.parse(new FileReader(yourFile)); 

공시 : 나는의 저자 이 라이브러리. 오픈 소스이며 무료입니다 (Apache V2.0 라이센스).

+1

설정을 완료하지 않았습니다. setRowProcessor (rowProcessor); – userRaj

+1

감사합니다! 내 대답이 업데이트되었습니다. –