2013-07-05 2 views
3

각 파일에 약 50,000 줄이 넘는 약 80 개의 파일을 읽는 가장 빠른 방법을 알아 내고 각 입력 파일의 행이 마스터에있는 열로 하나의 마스터 파일에 쓰는 데 도움이 필요합니다. . 마스터 파일은 줄 수를 처리 할 수 ​​없으므로 Microsoft 제품이 아닌 메모장과 같은 텍스트 편집기에 작성해야합니다.대용량의 여러 파일을 읽는 가장 좋은 방법

File1_Row1,File2_Row1,File3_Row1,... 

File1_Row2,File2_Row2,File3_Row2,... 

File1_Row3,File2_Row3,File3_Row3,... 

등 지금까지이 개 솔루션을 시도했습니다

:

  1. 가 개최 가변 배열을 만들기

    예를 들어, 마스터 파일은 다음과 같이 보일 것이다 각 파일의 내용을 배열에 저장 한 다음 모든 파일의 모든 행을 읽은 후에 마스터 파일을 작성하십시오. 이 솔루션의 문제점은 Windows OS 메모리가 너무 많은 가상 메모리를 사용하고 있다는 오류가 발생한다는 것입니다.

  2. 특정 줄 번호를 읽는 80 개의 파일 각각에 대해 동적으로 판독기 스레드를 만들고 모든 스레드가 한 줄의 읽기를 마친 후 해당 값을 결합하고 파일에 쓰고 모든 파일의 각 줄마다 반복합니다. 이 솔루션의 문제점은 매우 느리다는 것입니다.

아무도 빠른 속도로 많은 큰 파일을 읽는 더 좋은 솔루션을 가지고 있습니까?

+8

"... 메모장처럼 Microsoft 제품이 아닙니다 ..."-이 문제는 싫지만 메모장은 Microsoft 제품 –

+1

...이며 텍스트 파일은 텍스트 파일입니다. 즉, 'NotePadFileStream'이 없습니다. – ChiefTwoPencils

답변

5

가장 좋은 방법은 출력 파일에 대해 StreamReaderStreamWriter으로 입력 파일을 여는 것입니다. 그런 다음 각 리더를 반복하고 한 줄을 읽고 마스터 파일에 씁니다. 이 방법을 사용하면 한 번에 한 줄씩 만로드하므로 메모리가 최소한으로 유지되어야합니다. 37 초 만에 80 ~ 500,000 개의 라인 파일을 복사 할 수있었습니다. 예 :

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Diagnostics; 

class MainClass 
{ 
    static string[] fileNames = Enumerable.Range(1, 80).Select(i => string.Format("file{0}.txt", i)).ToArray(); 

    public static void Main(string[] args) 
    { 
     var stopwatch = Stopwatch.StartNew(); 
     List<StreamReader> readers = fileNames.Select(f => new StreamReader(f)).ToList(); 

     try 
     { 
      using (StreamWriter writer = new StreamWriter("master.txt")) 
      { 
       string line = null; 
       do 
       { 
        for(int i = 0; i < readers.Count; i++) 
        { 
         if ((line = readers[i].ReadLine()) != null) 
         { 
          writer.Write(line); 
         } 
         if (i < readers.Count - 1) 
          writer.Write(","); 
        } 
        writer.WriteLine(); 
       } while (line != null); 
      } 
     } 
     finally 
     { 
      foreach(var reader in readers) 
      { 
       reader.Close(); 
      } 
     } 
     Console.WriteLine("Elapsed {0} ms", stopwatch.ElapsedMilliseconds); 
    } 
} 

내가 한 모든 입력 파일 라인의 같은 번호를 가지고 있다고 가정하지만 적어도 하나 개의 파일을 사용하면 데이터 주신 때 읽는 유지하는 로직을 추가해야합니다.

+0

고마워, 너 천재 야! 그것은 위대한 작품. – jmm1487

3

Memory Mapped 파일을 사용하는 것이 적합하다고 판단됩니다. IO 작업에서 좋은 성능을 유지하면서 앱의 메모리를 압박하지 않는 무언가.

여기에 전체 문서 : Memory-Mapped Files

+0

대답은 (코멘트가 아닌) *이 질문에 대한 답변과 같습니다 * "어떻게 집을 짓나요?"* * "벽돌을 사용하십시오.이 링크의 벽돌에 대한 좋은 가이드가 있습니다"* . [mike z의 대답] (http://stackoverflow.com/a/17483103)에서 알 수 있듯이 OP가 이미 알고있는 도구를 사용하여이 질문에 대답하는 방법은 적어도 하나 있습니다. 문제는 도구를 사용하는 도구보다 도구를 사용하는 방법에 관한 것입니다. – shambulator

+1

@shambulator : 여기서 유효하지 않은 것을 보지 마십시오. 우리가 이야기하고있는 기술은 간결한 대답으로 설명 할 수있는 것이 아닙니다. 문서로 제시된 코드를 복사/붙여 넣기 할 수 있지만,이 문서가 우리가 말하는 기능에 대한 자세한 설명을 훨씬 잘 보여줄 것이라고 생각했습니다. – Tigran

+0

하지만 msdn 기사를 이해하면 메모리 매핑 된 파일에도 불구하고 개발자가 메모리 오버플로를 처리해야합니다. –

0

열린 파일 핸들의 배열을 가지고. 이 배열을 반복하고 각 파일의 행을 문자열 배열로 읽습니다. 그런 다음이 배열을 마스터 파일에 결합하고 마지막에 줄 바꿈을 추가하십시오.

이것은 두 번째 방법과 달리 단일 스레드이며 특정 줄을 읽지 않지만 항상 다음 줄을 읽습니다.

물론 다른 파일보다 줄이 적은 파일이 있으면 오류 증명이 필요합니다.

+0

이 방법이 스레드 방식보다 훨씬 빠르지 않다고 가정합니다. HDD 액세스를 위해 경쟁하는 여러 스레드를 없애지 만, 여전히 많은 랜덤 I/O를 가지고 있습니다. – Chris

+0

하나 이상 : http://stackoverflow.com/a/17483103/564226 - 버퍼를 사용하여 파일을 열거 나 명시적인 BufferedStream을 사용하여 파일을 열면 향상 될 수 있습니다. BTW, 나는 OP의 스레드 접근 방식은 다음 줄을 읽지 않았지만 항상 특정 줄 번호까지 인상을했다. – JeffRSon

+1

@jeffrson IIRC StreamReader/Writer는 기본적으로 버퍼링됩니다. –

3

컴퓨터에 충분한 메모리가 있다면 Parallel을 사용합니다.구조체를 호출하고, 미리 할당 된 배열로 각각의 파일을 읽는 등 :

:

string[] file1lines = new string[some value]; 
string[] file2lines = new string[some value]; 
string[] file3lines = new string[some value]; 

Parallel.Invoke(
() => 
{ 
    ReadMyFile(file1,file1lines); 
}, 
() => 
{ 
    ReadMyFile(file2,file2lines); 
}, 
() => 
{ 
    ReadMyFile(file3,file3lines); 
} 
); 

바로 아래의 샘플 코드를 사용해야 각 ReadMyFile 방법은, according to these benchmarks 텍스트 파일을 읽을 빠른 방법은

int x = 0; 
using (StreamReader sr = File.OpenText(fileName)) 
{ 
     while ((file1lines[x] = sr.ReadLine()) != null) 
     { 
       x += 1; 
     } 
} 

최종 출력을 작성하기 전에 각 파일의 데이터를 조작해야하는 경우 가장 빠른 방법은 read this article입니다.

그러면 각 문자열 []에 내용을 원하는대로 출력 할 수있는 한 가지 방법 만 있으면됩니다.

관련 문제