2013-05-01 2 views
5

주기적으로 쓰고있는 로그 파일을 읽으려고합니다. 프로그램은 정기적으로 로그 파일 내용을 읽고 파싱하여 일부 값을 추출합니다. 하지만 매번 전체 파일을 읽지 않으려합니다.C# - 주기적으로 파일의 마지막 부분을 읽는 가장 효과적인 방법

특정 줄의 파일을 읽을 수있는 방법이 있습니까?

예를 들어 첫 번째 읽기에는 파일에 100 개의 행이 있습니다. 나는이 값을 기록하고 다음에 내가 100 번째 줄부터 읽는 것을 읽고 현재 파일의 줄 번호를 저장한다.

효율적인 방법이 있습니까? 로그 파일이 약 100MB로 늘어나고 약 5 초마다 읽을 필요가 있습니다. 따라서 매번 전체 파일을 읽는 것이 효율적이지는 않습니다.

모든 의견을 크게 환영합니다.

+2

당신은 이러한 목적을위한 여러 파일에 파일이나 DB를 분할 할 수 – itsmatt

+0

당신은 Tail.NET http://www.codeproject.com/Articles/7568/Tail-NET 볼 수 있습니다. 하지만, 100MB 파일로 얼마나 많은 이익을 얻을지 모르겠습니다. 스트림에는 시작 인덱스가있는 경향이 있습니다. 그냥 사용하지 않는 이유는 무엇입니까? –

답변

3

나는 당신이 이것을 찾고 있는데, 어디에서 오프셋이 되길 원하는지 알고 싶습니다. 참조 :

using (FileStream fs = new FileStream(filepath, FileMode.Open, FileAccess.Read)) 
{ 
    fs.Seek(offset, SeekOrigin.End); 
} 

MSDN는 이제 파일 스트림 그러나 지금까지 다시 설정 한 파일을 가리키고는 것으로 '오프셋', 당신은 거기에서 읽을 수 있습니다.

+0

... 하, 2 분 너무 느립니다;) –

+0

@bland 감사합니다. 이 방법을 살펴 보겠습니다. 이게 날 위해 잘될 것 같아. – madu

2

로그가 추가되는 경우 잠금없이 읽기 전용 모드로 파일을 열어 볼 수 있습니다. 그렇게하면 다른 프로세스가 읽는 동안 다른 프로세스가이 프로세스에 쓸 수 있습니다.

var fs = new FileStream(path,FileMode.Open,FileAccess.Read, FileShare.ReadWrite); 
+0

파일의 길이를 기억하면 다음 읽기에서 그 위치로'탐색 '할 수 있습니다. – JosephHirn

1

빠르며 더러운 것이 있으면이 방법을 사용합니다. 이 경우에는 로그 덤프입니다 - 난 정말 내가 얻을, 난 그냥 말 (numBytes)에 무리를 원하는 얼마나 많은 라인에 대해 걱정하지 않는다 :

cmdLogReader = new System.IO.StreamReader(cmdLogFileIn); 

if (cmdLogReader.BaseStream.Length < (numBytes - 1)) { 
    return cmdLogReader.ReadToEnd; 
} else { 
    cmdLogReader.BaseStream.Seek(-numBytes, System.IO.SeekOrigin.End); 
    cmdLogReader.ReadLine(); 
    return cmdLogReader.ReadToEnd;   
} 

당신은 항상 처음에 BaseStream.Length을 절약 할 수 있으며, 이 값을 사용하여 다음 번에 다시 돌아갈 거리를 계산하십시오 (예 : numBytesBaseStream.Length - previousBaseStreamLength 또는 그 이상이 됨). 그러면 마지막 호출 이후에 추가 된 항목을 순차적으로 호출 할 수 있습니다.

무작위 금액을 역 추적 한 후에 가장 가까운 행으로 이동하는 것이 실제로 있기 때문에 ReadLine 통화를 건너 뛰어도됩니다. 선 경계에 착륙한다는 것을 알고 있다면 ReadToEnd 일 수 있습니다.

이것은 약간 껄끄 러운 구현이지만 매우 빠르므로 내가 사용하는 이유입니다.

+0

고맙습니다. BaseStream.Length 속성을 인식하지 못했고이 메서드를 사용하여 파일을 읽었습니다. 나는이 방법을 살펴볼 것이다. – madu

1

탐색이 잘 수행 할 수 있습니다. 그러나 전방 향방을 제공하고 싶습니다.

public static void Read() 
    { 
     var fs = new FileStream(@"G:\test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
     int lastReadCount = 0; 
     while (true) 
     { 
      var totalCountOfFile = fs.Length; 
      if (lastReadCount < totalCountOfFile) 
      { 
       var buffer = new byte[1024]; 
       int count = fs.Read(buffer, 0, buffer.Length); 
       lastReadCount += count; 
       Display(buffer); 
      } 
      Thread.Sleep(5000); 
     } 
    } 

    private static void Display(byte[] buffer) 
    { 
     var text = Encoding.UTF8.GetString(buffer.Where(p=>p != 0).ToArray()); 
     Console.Write(text); 
    } 
관련 문제