2014-11-02 1 views
1

작업

정수가 들어있는 거대한 파일 (약 20GB)이 있으며 C#에서이 파일을 읽으 려합니다.바이너리 파일에서 거대한 int-array를 읽으십시오.

간단한 방법

(바이트 배열) 메모리에 파일을 읽기가 매우 빠르고 (AN SSD를 사용하여 전체 파일이 메모리에 맞는). 그러나 바이너리 리더 (메모리 스트림을 통해)로이 바이트를 읽을 때 ReadInt32 메소드는 파일을 메모리로 읽는 것보다 훨씬 오래 걸립니다. 나는 병목 현상을 디스크 IO로 예상했지만 변환이 필요합니다!

아이디어와

그것을 하나의 별 하나 ReadInt32-방법을 변환하지 않아도에 직접 int로 배열로 전체 바이트 배열을 주조 방법이 있나요 질문? 5499ms

  • 파일로 작성

    class Program 
    { 
        static int size = 256 * 1024 * 1024; 
        static string filename = @"E:\testfile"; 
    
        static void Main(string[] args) 
        { 
         Write(filename, size); 
         int[] result = Read(filename, size); 
         Console.WriteLine(result.Length); 
        } 
    
        static void Write(string filename, int size) 
        { 
         Stopwatch stopwatch = new Stopwatch(); 
         stopwatch.Start(); 
         BinaryWriter bw = new BinaryWriter(new FileStream(filename, FileMode.Create), Encoding.UTF8); 
         for (int i = 0; i < size; i++) 
         { 
          bw.Write(i); 
         } 
         bw.Close(); 
         stopwatch.Stop(); 
         Console.WriteLine(String.Format("File written in {0}ms", stopwatch.ElapsedMilliseconds)); 
        } 
    
        static int[] Read(string filename, int size) 
        { 
         Stopwatch stopwatch = new Stopwatch(); 
         stopwatch.Start(); 
         byte[] buffer = File.ReadAllBytes(filename); 
         BinaryReader br = new BinaryReader(new MemoryStream(buffer), Encoding.UTF8); 
         stopwatch.Stop(); 
         Console.WriteLine(String.Format("File read into memory in {0}ms", stopwatch.ElapsedMilliseconds)); 
         stopwatch.Reset(); 
         stopwatch.Start(); 
    
         int[] result = new int[size]; 
    
         for (int i = 0; i < size; i++) 
         { 
          result[i] = br.ReadInt32(); 
         } 
         br.Close(); 
         stopwatch.Stop(); 
         Console.WriteLine(String.Format("Byte-array casted to int-array in {0}ms", stopwatch.ElapsedMilliseconds)); 
    
         return result; 
        } 
    } 
    
    • 파일은 편리와 임시 byte[] 버퍼를 할당 할 수 3382ms
  • +3

    결국 변환을 수행해야합니다. 배열을 메모리로 읽어 들여 BitConverter를 사용하여 필요에 따라 배열에서 값을 가져올 수 있습니까? –

    +0

    http://stackoverflow.com/questions/3206391/directly-reading-large-binary-file-in-c-sharp-w-out-copying의 가능한 복제본입니다. –

    +0

    @PatrickHofman : 그는 이미 파일을 메모리로 읽는 방법을 알고 있습니다. –

    답변

    2

    에서 int로 배열을하는 주조 455ms

  • 바이트 배열에 메모리로 읽어 크기를 사용하고 Buffer.BlockCopy 메서드를 사용하여 바이트를 int[] 배열에 점진적으로 복사합니다. offset 대상 hugeIntArray 배열의 시작 인덱스 (현재 반복을 위해) 전류

    BinaryReader reader = ...; 
    int[] hugeIntArray = ...; 
    
    const int TempBufferSize = 4 * 1024 * 1024; 
    byte[] tempBuffer = reader.ReadBytes(TempBufferSize); 
    Buffer.BlockCopy(tempBuffer, 0, hugeIntArray, offset, TempBufferSize); 
    

    .

  • +0

    ReadBytes가 동일한 운명을 겪을 가능성이 있지만, 확실하지 않습니다. –

    +0

    먼저 ReadAllBytes를 사용하여 전체 파일을 메모리로 읽습니다. – user2033412

    +0

    이것은 훨씬 더 빠릅니다. 파일을 439ms, 에서 메모리로 읽어들입니다. 바이트 배열이 int 배열로 캐스팅되었습니다 (105ms). – user2033412

    관련 문제