2013-03-05 1 views
4

FileHelpers (http://www.filehelpers.net/)로 매우 큰 CSV 파일을 구문 분석하려고합니다. 이 파일은 압축 된 1GB 및 압축 해제 된 약 20GB입니다.FileHelpers가 큰 CSV 파일을 구문 분석 할 때 OutOfMemoryException을 throw합니다.

 string fileName = @"c:\myfile.csv.gz"; 
     using (var fileStream = File.OpenRead(fileName)) 
     { 
      using (GZipStream gzipStream = new GZipStream(fileStream, CompressionMode.Decompress, false)) 
      { 
       using (TextReader textReader = new StreamReader(gzipStream)) 
       { 
        var engine = new FileHelperEngine<CSVItem>(); 
        CSVItem[] items = engine.ReadStream(textReader);       
       } 
      } 
     } 

FileHelpers는 OutOfMemoryException을 발생시킵니다.

테스트 실패 : 'System.OutOfMemoryException'유형의 예외가 발생했습니다. System.OutOfMemoryException : 형식이 예외 'System.OutOfMemoryException'throw되었습니다. FileHelpers.StringHelper.ExtractQuotedString에서 System.Text.StringBuilder.Append (char 값) (AT System.Text.StringBuilder.Append (char 값, INT32 반복 횟수)에 System.Text.StringBuilder.ExpandByABlock (INT32 minBlockCharCount)에서 LineInfo 라인 에서 FileHelpers.RecordInfo.StringToRecord (LineInfo 라인)에서 FileHelpers.FieldBase.ExtractValue (LineInfo 라인)에서 FileHelpers.DelimitedField.ExtractFieldString (LineInfo 라인)에서 숯불 quoteChar 부울 allowMultiline) FileHelpers.FileHelperEngine 1.ReadStream(TextReader reader, Int32 maxRecords, DataTable dt) at FileHelpers.FileHelperEngine 1 .ReadStream (TextReader 판독기)

FileHelpers로 이처럼 큰 파일을 구문 분석 할 수 있습니까? 그렇지 않다면 누구나이 파일을 파싱하는 접근법을 권장 할 수 있습니까? 감사.

+0

BowserKingKoopa 20GB라면 파일을 압축 해제 할 때 사용 가능한 공간이 얼마나되는지 분명히 알 수 있습니다. 40GB가 없는지 확인하기 위해 두 배가됩니다. – MethodMan

+1

~ 20GB의 데이터를 RAM에 저장 하시겠습니까? 정말 ? – digEmAll

+0

TextReader 대신 BinaryReader를 사용해야합니까? FileHelpers가 버퍼 크기를 처리합니까? 아니면 직접 설정해야합니까? 당신이 SQLite는 DB를 생성하지 않는 예를 들어 테이블에 그 CSV를 가져 이유는 제 생각에는 – MethodMan

답변

9

당신은 이런 식으로 기록하여 기록을 작업해야합니다.

+2

감사! FileHelperAsyncEngine은 제가 찾고 있던 것입니다. – BowserKingKoopa

+0

Flipn 우수한 친구 – Eminem

0

이것은 완전한 대답은 아니지만, 20GB의 csv 파일이있는 경우 독자가 메모리에 압축 된 모든 내용을 보관하지 않는 한 20GB 이상 있으면 전체 메모리를 한 번에 메모리에 저장해야합니다. 당신은 청크로 파일을 읽을 필요가 있고, 당신이 엄청난 양의 램을 가지고 있지 않다면, 모든 것을 배열에 집어 넣는 데 사용하는 해결책은 작동하지 않을 것이다.

당신은 좀 더 이런 루프를 필요

CsvReader reader = new CsvReader(filePath) 
CSVItem item = reader.ReadNextItem(); 
while(item != null){ 
    DoWhatINeedWithCsvRow(item); 
    item = reader.ReadNextItem(); 
} 

C#의 메모리 관리는 당신이 그들에 대한 참조를 유지하지 않는 한, 당신이 그들을 통과로 이전 CSVItems 처분 똑똑 할 것이다 주위를 어슬렁.

더 나은 버전은 CSV (예 : 10,000 행)에서 청크를 읽은 다음 모든 것을 처리 한 다음 다른 청크를 얻거나 처리 순서를 신경 쓰지 않으면 DoWhatINeedWithCsvRow에 대한 작업을 만듭니다. 당신은 당신은 단지 레코드의 메모리 시간을 사용하는 것이 비동기 aproach를 사용하는 경우

string fileName = @"c:\myfile.csv.gz"; 
    using (var fileStream = File.OpenRead(fileName)) 
    { 
     using (GZipStream gzipStream = new GZipStream(fileStream, CompressionMode.Decompress, false)) 
     { 
      using (TextReader textReader = new StreamReader(gzipStream)) 
      { 
      var engine = new FileHelperAsyncEngine<CSVItem>(); 
      using(engine.BeginReadStream(textReader)) 
      { 
       foreach(var record in engine) 
       { 
        // Work with each item 
       } 
      } 
      } 
     } 
    } 

, 그리고 훨씬 더 빨라집니다 :

관련 문제