2011-02-11 6 views
2

내가해야 할 일은 각각 약 2GB의 파일 (txt)이 거의 없다는 것입니다. '%% XGF NEW_SET' 표시가 나타날 때마다 파일을 잘라 내야합니다. 새 파일을 만들어 저장해야합니다. 나는이 표식이 약 40 ~ 50 줄마다 등장한다고 생각한다. 각 라인은 4 ~ 20 개의 문자를가집니다. 큰 파일을 수천 개의 작은 파일로 잘라낸 다음 나중에 처리해야합니다. 나는 그런 샘플 코드를 생각했다.효율적인 파일 읽기 및 잘라 내기

 DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
     var files = di.GetFiles(); 
     int count = 0; 
     bool hasObject = false; 
     StringBuilder sb = new StringBuilder(); 
     string line = ""; 
     foreach (var file in files) 
     { 
      using (StreamReader sr = new StreamReader(file.FullName,Encoding.GetEncoding(1250))) 
      { 
       while ((line = sr.ReadLine()) != null) 
       { 
        //when new file starts 
        if (line.Contains("%%XGF NEW_SET")) 
        { 
         //when new file existed I need to store old one 
         if (hasObject) 
         { 
          File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
          sb.Length = 0; 
          sb.Capacity = 0; 

         } 
         //setting exist flag 
         hasObject = true; 
        } 
        //when there is no new object 
        else 
         //when object exists adding new lines 
         if (hasObject) 
          sb.AppendLine(line); 
       } 
       //when all work done saving last object 
       if (hasObject) 
       { 
        File.WriteAllText(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name), sb.ToString()); 
        sb.Length = 0; 
        sb.Capacity = 0; 
       } 
      } 
     } 
    } 

그래서 내 표본은 높은 효율을 필요로합니다. 솔루션을 개선 할 수있는 아이디어가 있습니까? 감사합니다

+0

는'%% XGF NEW_SET' 분할 선에 유일하게인가? 그렇지 않은 경우이 줄을 버리므로 다른 정보가 손실됩니다. –

+2

당신의 방법은 : 원본 파일에서 스트림을 열고, 모든 섹션 브레이크마다 새로운 파일에 기록하십시오. 코드 가독성을 최적화하고 문자열 작성자를 필요로하지 않는다는 점을 제외하면이 방법을 훨씬 빨리 구현할 수있는 방법을 알지 못합니다. 쓰기 작업을 쓰레드에 스레딩하는 것은 당신이 다른 드라이브에서 읽고 재 작성하는 경우에 도움이 될 것입니다. – deepee1

답변

2

현재 코드가 제공하는 것과 비교해 어떤 종류의 효율성이 필요합니까?

개인적으로는 개인적으로는 조금씩 다르게 할 것입니다. 독자와 작가는 항상 열려 있어야하며 "잘린"줄이 아니라면 읽은 각 줄을 작성하십시오. 새로운 것을 시작하십시오. 나는 특히 거기에 다른 효율성을 기대하지 않을 것이다.

1

나는 다음 객체가 올 때까지 출력 파일 스트림을 작성하여 StringBuilder를 완전히 제거 할 필요가 없습니다. 그런 다음 새 개체에서 새 파일 스트림으로 전환하십시오.

0

모든 정보 주셔서 감사합니다. 고려 사항을 고려한 후에 코드를 다음과 같이 수정했습니다.

DirectoryInfo di = new DirectoryInfo(ConfigurationManager.AppSettings["BilixFilesDir"]); 
//getting all files from dir 
var files = di.GetFiles(); 
int count = 0; 
bool hasObject = false; 
string line = ""; 
StreamWriter sw = null; 
foreach (var file in files) 
{ 
    using (StreamReader sr = new StreamReader(file.FullName, Encoding.GetEncoding(1250))) 
    { 
     while ((line = sr.ReadLine()) != null) 
     { 
      //when new file starts 
      if (line.Contains("%%XGF NEW_SET")) 
      { 
       //when new file existed I need to store old one 
       if (hasObject) 
       { 
        sw.Close(); 
       } 
       else 
       { 
        //creating new file and setting exist flag 
        hasObject = true; 
        sw = new StreamWriter(string.Format("{0}/{1}-{2}", ConfigurationManager.AppSettings["OutputFilesDir"], count++, file.Name)); 
        //Bill bill = new Bill();        
       } 
      } 
      else 
       //when object exists adding new lines 
       if (hasObject) 
        sw.WriteLine(line); 
     } 
     //when all work done saving last object 
     if (hasObject) 
     { 
      sw.Close(); 
      hasObject = false; 
     } 
    } 
} 
sw.Dispose(); 

그런 식으로 생각하니?

한 가지 더해야 할 일 : 큰 파일에는 다른 문서를 저장할 수 있습니다. 그들 모두는 시작을위한 다른 마킹을 가지고 있습니다. 20 종류의 문서가 있다고 가정 해 보겠습니다. 때로는 동일한 표시 시작이 있지만 문서 안에는 문서의 유형을 인식 할 수있는 몇 가지 추가 표시가 있습니다. 즉, 예를 들어 두 개의 문서가 "%% XGF NEW_SET"과 같은 마킹 시작을 가지고 있지만 하나는 "BILL_A"과 같은 마킹에 후자가 있습니다. 그리고 문서의 일부 인덱스와 해당 유형이 포함 된 문자열을 사용하여 모든 잘라 내기 파일에 대해 하나 이상의 파일을 만들어야합니다. 그래서 기본적으로 내 StreamWriter 저장하기 전에 모든 Indexes 및 StringBuilder 생각했던 방식으로 문서 형식을 추출해야합니다. 이렇게 높은 효율을 필요로 할 때 다음 장소입니다. 좋은 정보 요?

0

.NET에서 파일을 읽고 쓰는 데는 여러 가지 방법이 있습니다. 나는 벤치 마크 프로그램을 작성하고 내 블로그에 결과를 얻을 수있다 : 성능을 필요로하는 경우에서 Windows에서 ReadFile과의 WriteFile 방법을 사용하는 것이 좋습니다

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

. 내 벤치 마크 결과에 따르면 동기식 I/O 메소드를 사용하면 파일을 읽는 데 가장 빠른 .NET 클래스 인 FileStream에 대해 더 나은 성능을 보여 주므로 비동기식 메서드는 사용하지 마십시오. C#에서 클래스의 기능을 캡슐화 한 클래스를 작성했습니다. ReadFile 및 WriteFile 기능을 사용하면 쉽게 사용할 수 있습니다.

흥미로운 또 다른 결과는 행 .vs를 읽는 것과 같은 것을 보았습니다. 65,536 바이트 블록 단위로 데이터를 읽고 라인으로 파싱합니다. 블록 단위로 데이터를 읽은 다음 프로그램 내부의 행으로 파싱하는 것이 더 효율적이라는 것이 밝혀졌습니다. 내 다운로드에는이를 수행하는 방법에 대한 몇 가지 예가 있습니다.

StreamReader보다 빠르면 다운로드하여 사용해보고 여기에 다시보고하거나 내 블로그에 의견을 남기는 것이 좋습니다. 제한된 벤치 마크 결과에 따르면 훨씬 빠릅니다.

프로그램의 성능을 향상시키는 또 다른 방법은 여러 스레드를 만들고 각 스레드가 파일을 처리하도록하는 것입니다. 당신은 큰 파일이 몇 개 있다고 말했기 때문에 각각의 큰 파일마다 별도의 스레드가 있도록 파일을 해체했습니다.

문자열로 많은 작업을 수행한다면 확실히 StringBuilder를 사용해야합니다. 그러나 더 효율적인 방법은 데이터를 바이트 배열로 읽어 들인 다음 출력을 위해 바이트 배열을 만드는 것입니다. 그게 StringBuilder를 사용하는 것보다 더 효율적이지 않다면 놀랄 것입니다.

밥 브라이언 MCSD

관련 문제