2012-09-06 10 views
2

환경 : 모든 .Net Framework 환영. 24/7로 기록되는 로그 파일이 있습니다.텍스트 파일 추가 및 읽기

로그 파일을 읽고 데이터를 처리하는 응용 프로그램을 만들려고합니다.

로그 파일을 효율적으로 읽는 가장 좋은 방법은 무엇입니까? 나는 FileSystemWatcher와 같은 것으로 파일을 모니터링하는 것을 상상한다. 그러나 응용 프로그램에서 처리 된 동일한 데이터를 읽지 않도록하려면 어떻게해야합니까? 또는 응용 프로그램이 알려지지 않은 이유로 중단되었다고 가정합니다. 마지막으로 중단 된 부분을 어떻게 알 수 있습니까?

일반적으로 로그 파일에있는 페이로드 주변에는 머리글과 바닥 글이 있습니다. 콘텐츠의 id 필드 일 수도 있습니다. 아직 거기에있는 id 필드에 대해서는 확실하지 않습니다.

어쩌면 북마크로 사용하는 어딘가에 라인 수를 저장하는 것도 상상했을 것입니다.

답변

1

글쎄, 당신은 당신의 특별한 경우에 대한 자신의 마법을 알아 내야 할 것입니다. 잘 알려진 텍스트 인코딩을 사용한다면 매우 간단 할 것입니다. System.IO.StreamReader를 살펴보면 ReadLine(), DiscardBufferedData() 메서드 및 BaseStream 속성입니다. 파일의 마지막 위치를 기억하고 나중에 해당 위치로 되감기를하고 파일 만 추가한다고 확신 할 경우 다시 읽기 시작할 수 있어야합니다. 고려해야 할 다른 사항이 있으며 이에 대한 보편적 인 대답은 하나도 없습니다. 그냥 순진 예를 들어

(당신은 여전히 ​​작동하도록 많이 조정해야 할 수도 있습니다) : 로그에서 파일의 전체 내용을 읽을뿐만 아니라 제거 라인 분명한 이유를 들어

static void Main(string[] args) 
    { 
     string filePath = @"c:\log.txt"; 
     using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) 
     { 
      using (var streamReader = new StreamReader(stream,Encoding.Unicode)) 
      { 
       long pos = 0; 
       if (File.Exists(@"c:\log.txt.lastposition")) 
       { 
        string strPos = File.ReadAllText(@"c:\log.txt.lastposition"); 
        pos = Convert.ToInt64(strPos); 
       } 
       streamReader.BaseStream.Seek(pos, SeekOrigin.Begin); // rewind to last set position. 
       streamReader.DiscardBufferedData(); // clearing buffer 
       for(;;) 
       { 
        string line = streamReader.ReadLine(); 
        if(line==null) break; 

        ProcessLine(line); 
       } 
       // pretty sure when everything is read position is at the end of file. 
       File.WriteAllText(@"c:\log.txt.lastposition",streamReader.BaseStream.Position.ToString()); 
      } 
     } 
    } 
+0

"파일의 마지막 위치를 기억하고 나중에 그 위치로 되감기를하고 다시 읽기 시작할 수 있어야합니다."이 작업을 수행하기위한 아이디어는 무엇입니까? 마지막 줄을 저장하는 것이 좋은 생각입니까? 코드에서와 같은 위치에 되감기는 무엇입니까? – Rod

+0

필자는 파일에서 위치를 저장하는 것을 의미했습니다. 예를 들어 streamReader.BaseStream.Position과 같은 값은 길이가 150자인 1000 줄의 150000과 같을 수 있습니다. 마지막 줄 읽기를 저장하는 것은 중복이있을 수 있으므로 거의 의미가 없습니다. 각 문자열이 고유 한 경우 유용 할 수 있지만 즉시 Seek() 작업 대신 파일에있는 모든 문자열을 읽을 때까지 약간의 시간이 필요합니다. – aiodintsov

1

을 파일 (응용 프로그램에로드 한 후)이 문제가 아닙니다.

내가 부분적인 해결책으로 생각할 수있는 것은 작은 데이터베이스 (본격적인 MySQL/MS SQL/PostgreSQL 인스턴스보다 훨씬 작음)와 로그 파일에서 읽은 테이블을 채우는 것입니다. 전원이 차단 된 상태에서 기계가 다시 부팅 되더라도 대부분의 관계형 데이터베이스는 상태를 쉽게 복원 할 수 있어야합니다. 이 솔루션을 사용하려면 로그 파일에서 행을 식별하는 데 사용할 수있는 일부 데이터가 필요합니다 (예 : 기록 된 작업의 정확한 시간, 작업이 수행 된 시스템 등)

1

파일 .ReadLines (filename) 함수는 LINQ와 함께 이런 식으로 매우 편리 할 것입니다. ReadAllLines()는 전체 텍스트 파일을 문자열 [] 배열로 메모리에로드하지만 ReadLines를 사용하면 파일을 탐색 할 때 즉시 행을 열거 시작할 수 있습니다. 이렇게하면 시간을 절약 할 수있을뿐 아니라 한 번에 하나씩 각 라인을 처리 할 때 메모리 사용량을 매우 낮게 유지합니다. 문장을 사용하는 것은 중요합니다. 왜냐하면이 프로그램이 중단되면 파일 스트림을 닫아서 작성자를 비우고 작성되지 않은 내용을 파일에 저장하기 때문입니다. 그런 다음 시작되면 이미 읽은 모든 파일을 건너 뜁니다.

MaciekTalaska가 언급 한 바와 같이
int readCount = File.ReadLines("readLogs.txt").Count(); 
using (FileStream readLogs = new FileStream("readLogs.txt", FileMode.Append)) 
using (StreamWriter writer = new StreamWriter(readLogs)) 
{ 
    IEnumerable<string> lines = File.ReadLines(bigLogFile.txt).Skip(readCount); 
    foreach (string line in lines) 
    { 
     // do something with line or batch them if you need more than one 
     writer.WriteLine(line); 
    } 
} 

, 나는 강력하게이 7 분의 24에 기록 뭔가가 아주 큰 얻을 것이다 경우 데이터베이스를 사용하는 것이 좋습니다. 파일 시스템은 단순히 이러한 볼륨을 처리 할 수있는 기능이 없으므로 데이터베이스가 산들 바람을 불어 넣을 수있는 솔루션을 개발하기 위해 많은 시간을 할애해야합니다.

1

파일에 기록되는 이유가 있습니까? 파일은 사용하기 쉽고 가장 낮은 공통 분모이기 때문에 문제가 될 수있는 파일이 비교적 적습니다. 그러나 파일은 제한되어 있습니다.말했듯이 파일을 읽을 때 파일에 대한 쓰기가 완료된다는 보장은 없습니다. 로그에 기록하는 여러 응용 프로그램이 서로를 방해 할 수 있습니다. 쉬운 분류 또는 필터링 메커니즘이 없습니다. 로그 파일은 매우 빠르게 커질 수 있으며 오래된 이벤트 (예 : 24 시간 이상 된 파일)를 백업 및 보존을 위해 별도의 파일로 쉽게 옮길 수 없습니다.

대신 로그를 데이터베이스에 기록하는 것을 고려할 것입니다. 테이블 구조는 매우 간단 할 수 있지만 거의 보편적으로 이해되는 구문을 사용하여 검색, 정렬 및 필터링하는 트랜잭션의 이점을 얻습니다 (추출 또는 백업이 용이함). 로드 스파이크가 걱정되면 SQL Server에 http://msdn.microsoft.com/en-us/library/ms190495.aspx과 같은 메시지 큐를 사용하십시오.

전환을 쉽게하려면 log4net과 같은 로깅 프레임 워크를 사용해보십시오. 이 코드는 코드에서 대부분 추상화됩니다.

또 다른 대안은 syslog과 같은 시스템을 사용하거나 서버가 여러 대 있고 로그가 많은 경우 flume과 같은 시스템을 사용하는 것입니다. 원본 컴퓨터에서 로그 파일을 이동하면 훨씬 더 효과적으로 다른 컴퓨터에 저장하거나 검사 할 수 있습니다. 그러나 이것들은 아마도 당신의 현재 문제에 대한 과잉 공격 일 것입니다.