2013-10-07 64 views
2

我有一個程序不斷將其日誌寫入文本文件。 我沒有它的源代碼,所以我不能以任何方式修改它,它也受Themida保護。動態讀取文本文件上的更改c#

我需要讀取日誌文件並根據文件內容執行一些腳本。 我無法刪除該文件,因爲持續寫入該文件的程序已鎖定該文件。 那麼讀取文件的更好方法是什麼,只讀取文件的新行? 保存最後一行位置?或者是否有一些對於在C#中解決它有用?

+0

相關http://stackoverflow.com/questions/13185319/how-to-detect-real-time-change-of-text-files –

回答

4

也許使用FileSystemWatcher以及使用FileShare打開文件(因爲它正在被另一個進程使用)。漢斯帕桑特提供了一個很好的答案對於這部分here

var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 
     using (var sr = new StreamReader(fs)) { 
      // etc... 
     } 

看一看這個question和接受的答案,也可能會有幫助。

2
using (var fs = new FileStream("test.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete)) 
using (var reader = new StreamReader(fs)) 
{ 
    while (true) 
    { 
     var line = reader.ReadLine(); 

     if (!String.IsNullOrWhiteSpace(line)) 
      Console.WriteLine("Line read: " + line); 
    } 
} 

我測試了上面的代碼,它的工作原理是,如果您試圖一次讀取一行。唯一的問題是,如果在完成寫入之前將該行刷新到文件中,那麼您將在多個部分中讀取該行。只要記錄系統一次寫入每一行,它應該沒問題。

如果沒有,那麼你可能想要讀入緩衝區而不是使用ReadLine,所以你可以通過檢測每個Environment.NewLine子串來自己分析緩衝區。

+0

也是一個很好的答案,它會一直等到整行可用,但它會連續鎖定文件(這不一定是個問題)。 – Todd

2

您可以繼續在緊密循環中調用ReadToEnd()。即使到達文件末尾,它也會返回一個空字符串「」。如果有更多數據寫入文件,它將在隨後的調用中將其提取出來。

while (true) 
{ 
    string moreData = streamReader.ReadToEnd(); 
    Thread.Sleep(100); 
} 

請記住,您可能會以這種方式讀取部分行。此外,如果你正在處理非常大的文件,你可能需要另一種方法。

+0

這是一個很好的答案,非常簡單。礦井只是更好,因爲大部分時間文件沒有被鎖定。 – Todd

1

日誌文件被「不斷」更新,所以你真的不應該使用FileSystemWatcher每次引發事件的文件更改。這會不斷觸發,你已經知道它將會變化很大。

我建議使用定時器事件來定期處理文件。 Read this SO answer有很好的使用模式System.Threading.Timer 。保持文件流打開,以便每次讀取或重新打開,並且Seek到最後一次成功讀取的結束位置。通過「上次成功讀取」,我的意思是你應該封裝讀取和驗證完整的日誌行。一旦您成功讀取並驗證了一條日誌行,那麼您在下一個Seek有一個新的位置。

請注意,System.Threading.Timer將在由ThreadPool保留業務的系統提供的線程上執行。對於短期任務來說,這更適合專用線程。

+0

請問您是否更詳細?我有或多或少相同的問題。我有一個很大的文件(60MB),這個文件一直是從一臺機器寫入的。現在我應該讀取所​​有寫在那裏的數據。我是否也可以不時刪除該文件? –

0

在另一篇文章中使用此答案c# continuously read file

這一個是非常有效的,它每秒檢查一次,如果文件大小已經改變。所以文件通常不會被鎖定。

其他答案是非常有效和簡單。他們中的一些人會不斷讀取鎖定文件,但這對大多數人來說可能不是問題。