2012-11-05 6 views
5

이이 접선 an earlier question of mine.정규식을 사용하여 파일을 읽으시겠습니까?

관련이는 본질적으로 그 문제의 해결책은 잘 작동했지만 지금은 훨씬 더 큰 분석 응용 프로그램에서 작동하도록 적응해야합니다. StreamReader.ReadToEnd()을 단순히 사용하는 것은 허용되지 않습니다. 왜냐하면 내가 읽을 파일 중 일부가 매우 매우 크기 때문입니다. 실수가 있었고 누군가 정리하는 것을 잊어 버린 경우 이론적으로는 기가 바이트가 될 수 있습니다. 분명히 나는 ​​그것의 끝까지 읽을 수 없다.

불행하게도, 내가 읽고있는 일부 데이터 행에 스택 추적이 포함되어 있기 때문에 정상적인 읽기 라인도 허용되지 않습니다. 분명히 포맷에 /r/n을 사용합니다. 이상적으로, 정규식에 대한 일치를 검색 할 때까지 앞으로 읽도록 프로그램에 지시하고 싶습니다. .net에서이 작업을 수행 할 수있는 기능이 있습니까? 그렇지 않다면 필자는 글쓰기에 대한 제안을받을 수 있습니까?

편집 : 그것은 좀 더 쉽게 내 질문에 따를 수 있도록, 여기에 적응 코드의 중요한 부분 중 일부의 붙여 넣기입니다 :

foreach (var fileString in logpath.Select(log => new StreamReader(log)).Select(fileStream => fileStream.ReadToEnd())) 
{ 
    const string junkPattern = @"\[(?<junk>[0-9]*)\] \((?<userid>.{0,32})\)"; 
    const string severityPattern = @"INFO|ERROR|FATAL"; 
    const string datePattern = "^(?=[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2},[0-9]{3})"; 
    var records = Regex.Split(fileString, datePattern, RegexOptions.Multiline); 
    foreach (var record in records.Where(x => string.IsNullOrEmpty(x) == false)) 
    ...... 

문제는의 Foreach에있다. .Select(fileStream => fileStream.ReadToEnd())가 심하게 기억을 날려 버릴 테니, 나는 단지 그것을 알고 있습니다.

+4

그리고 거기에 RegEx를 사용하는 것과 관련하여 정말로 신경 쓰지 않는 주된 이유 중 하나가 있습니다. 간단한 구문 분석기를 작성했다면 새로운 행을 처리하기 위해이를 간단하게 적용 할 수 있습니다. –

+0

@JonathanWood 전체 레코드를 가지고 나면 정규 표현식은 개별 레코드를 구문 분석하는 데 아주 좋습니다. 나는 필요한 모든 정보를 쏟아 내고 관련 분야에 곧바로 간다. 문제는이 경우 파일 입력입니다. 단순히 파일 하나를 한 번에 제공 할만큼 융통성이없는 것처럼 보입니다. 하지만 그건 가짜로 보입니다. 그렇죠? 이것은 드문 문제가 될 수 없습니다. – tmesser

+1

그래서 스택 추적에는/r/n이 있습니다. 왜 그것은 readline을 제거합니까? – Paparazzi

답변

1

먼저 const 정의를 클래스 선언으로 옮겨야합니다. 컴파일러가이를 대신 처리하지만 코드 가독성을 높이기 위해 직접 작성해야합니다. @Blam가 언급 한 바와 같이

,이 같은 쌍의 StringBuilderStreamReader.ReadLine, 뭔가를 사용한다 : 나는 당신의 문제에 대해 뭔가를 이해하지 않은 경우, 의견이 명확히하십시오

foreach(var filePath in logpath) 
{ 
    var sbRecord = new StringBuilder(); 
    using(var reader = new StreamReader(filePath)) 
    { 
     do 
     { 
      var line = reader.ReadLine(); 
      // check start of the new record lines 
      if (Regex.Match(line, datePattern) && sbRecord.Length > 0) 
      { 
       // your method for log record 
       HandleRecord(sbRecord.ToString()); 
       sbRecord.Clear(); 
       sbRecord.AppendLine(line); 
      } 
      // if no lines were added or datePattern didn't hit 
      // append info about current record 
      else 
      { 
       sbRecord.AppendLine(line); 
      } 
     } while (!reader.EndOfStream) 
    } 
} 

.
ThreadPool을 사용하면 응용 프로그램의 속도를 위해서만 줄 작업을 예약 할 수 있습니다.

+0

텍스트 스트림을 표준화 된 토큰으로 구문 분석 할 수 없다는 것이 절대적으로 모호하다고 느꼈기 때문에 저수준의 스트림을 처리하는 자체 솔루션을 코딩하는 일이 발생했습니다. 그러나, 기본적으로 다른 사람을 위해 이것은 당신이해야 할 일을 어느 정도합니다. – tmesser

+0

@YYY 기록 용으로 여기에 코드를 제공 할 수 있습니까? 나는 이것이 흥미로울 것이라고 생각한다. – VMAtm

+0

내가하고 싶어하는만큼, 곧 일부 뱅킹 소프트웨어의 일부가 될 것이므로 독점적입니다. 즉 며칠을 쉬는 시간에 내 아젠다에있는 것들 중 하나가 오픈 소스 버전을 만들어 내 github에 추가하는 것이므로 솔루션을 확장 할 수 있습니다. 지금 당장은 고정 바이트 수를 읽고 파일 위치를 유지합니다.이 파일 위치는 프로젝트 컨텍스트에서 훌륭하게 작동하지만 좋은 일반화 된 솔루션은 아닙니다. 그 첫 번째 작품을 복제/위생 처리하고 github에 추가하면 그 야망은 계속 될 것입니다. – tmesser

관련 문제