2017-05-06 15 views
3

1,000,000 개의 Java CSV 파일을 읽으려고합니다. OpenCSV 라이브러리를 사용하고 있는데, 30,000 줄의 작은 파일에서 잘 작동합니다. 30 분 안에 처리합니다. 그러나 백만 줄의 파일을 읽으려고하면 끝나지 않습니다.Java에서 큰 CSV 파일 읽기

지금 나는 그것이 실제로 중지 할 때,보고, 테스트, 이진 검색의 내 자신의 버전을 사용하여, 내가 먼저 등 50 만 다음 라인, 25 만 등을 읽으려고, 나는 그것을 발견 쉽게145k 행을 표시하며 0.5-0.7sec이고 150k도 완료되지 않습니다.

저는 완전히 검색 했으므로 BufferedReader, BufferedInputStream 등을 사용하여 여러 가지 솔루션을 찾았습니다. 해결 된 해결책은 없습니다. 여전히 145-150k 행 사이에서 실패합니다.

try { 
     // BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("myFile.csv")); 
     CSVReader csvReader = new CSVReader(new InputStreamReader 
       (new BufferedInputStream(new FileInputStream("myFile.csv"), 8192 * 32))); 
     try { 
      int count = 0; 
      String[] line; 
      long timeStart = System.nanoTime(); 
      while((line = csvReader.readNext()) != null){ 
       count ++; 
       if(count >= 150000){ 
        break; 
       } 
      } 
      long timeEnd = System.nanoTime(); 
      System.out.println("Count: " + count); 
      System.out.println("Time: " + (timeEnd - timeStart) * 1.0/1000000000 + " sec"); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } catch (FileNotFoundException e) { 
     System.out.println("File not found"); 
    } 

당신은 내가 더 큰 버퍼를 설정 시도 볼 수 있듯이이 내 코드의 관련 부분입니다

(145000와 150000 교환 프로그램이 < 1 초에 실행됩니다 것입니다) 크기뿐. 나는 Readers, Input Streams 등의 다양한 조합을 시도했지만 아무런 차이를 만들지 않았습니다.

나는 이것을 어떻게 할 수 있는지 궁금합니다. 한 번에 100k 라인을 읽고, 다음 100k를 계속 읽는 방법이 있습니까?

또한 저는 OpenCSV 라이브러리가 반드시 포함되어 있지 않은 다른 솔루션에 대해 열려 있습니다. 방금 csv 파일을 구문 분석하기 위해 단순성을 위해이 파일을 사용했습니다.

+0

'끝내지 않는다'는 말은 .... 실제로 무엇입니까? 교착 상태, 메모리 부족 등 ... 디버거를 사용하여 최대 처리량을 확인하거나 루프에 sysouts를 넣어 처리 중인지 확인하십시오. – Adam

답변

2

아마도 문제는 CSV 파일의 줄 수에 관한 것이 아니라 내용에 관한 것입니다. 어쩌면 145k와 150k 사이의 선에 어떤 데이터가있어 어플리 케이 션이 끝나지 않을 수도 있습니다.

첫 번째 145k 줄을 파일에서 복사하여 새 CSV 파일에 붙여 넣으면 1m 줄까지 확인할 수 있습니다. 응용 프로그램이이 새 파일을 처리 할 수있는 경우, 행 수가 아닌 데이터에 문제가 있습니다.

3

방금 ​​OpenCSV 구현을 살펴 보았습니다. 파일이 크고 많은 레코드가 포함되어 있기 때문에 그러한 동작을 설명 할 수있는 것이 아무것도 없습니다.

그러나 OpenCSV 웹 사이트에서 여러 데이터를 처리 할 수 ​​있습니다 :

포함 된 캐리지 리턴 (여러 줄에 걸쳐 즉, 항목)에 인용 된 항목을 처리.

나는 귀하의 경우, 150k 번째 레코드 어딘가에 잘못된 인용 된 항목이있는 레코드가 있다고 생각합니다. 기본 따옴표 char는 "입니다.이 경우

value,value,"badvalue,value 
value,value,value,value 

, 읽을 수있는 기록이 다음 줄에 계속 의미하는 중인 상태로 설정 IST OpenCSV 사용하는 파서 :이 기록처럼 될 수 있습니다. 그리고 CSVReader.readNext()에 대한 호출은 csv 레코드를 완료하는 데 필요한만큼의 행을 읽으려고합니다. 잘못 놓인 따옴표 문자와 일치하는 문자열이 없으면 버퍼가 고갈되거나 다른 오류가 발생할 때까지 읽고 읽고 읽습니다.

레코드를 찾으려면 파일을 읽은 것처럼 레코드를 계산하고 현재 수를 인쇄하십시오. 이것은 당신에게 마지막으로 유효한 레코드의 번호를 줄 것이고 그때는 멈추거나 멈출 것입니다.

그런 다음 파일을 한 줄씩 (CSVParser를 사용하지 않고 일반 줄만 읽음) 잘 읽고 알고있는 줄 수를 건너 뛰는 새 프로그램을 작성합니다. 그런 다음 거기에서 약 10 줄을 인쇄하면 분석 할 데이터가 있습니다.

+0

나는 P.J.와 Marat의 의견에 동의합니다. 위와 같은 프로그램을 계속 사용하고 싶다면 바이너리 방식으로 숫자 (145K가 작동하므로 147K를 사용하고 148K를 사용)를 줄이는 것이 좋습니다. 영원히 복용하기 시작하면 범위를 좁 힙니다. 그런 다음 실제 파일 (및 위/아래의 행)에서 해당 행을 보면 데이터가 잘못된 형식으로되기 시작하는 곳을 볼 수 있습니다. –