2010-08-10 98 views
70

我有一個Windows服務以簡單格式將其日誌寫入文本文件。如何在不鎖定的情況下讀取文本文件?

現在,我將創建一個小應用程序來讀取服務的日誌,並將現有日誌和添加的日誌顯示爲實時視圖。

問題是,該服務鎖定文本文件以添加新行,同時查看器應用程序鎖定文件以供閱讀。

服務代碼:

void WriteInLog(string logFilePath, data) 
{ 
    File.AppendAllText(logFilePath, 
         string.Format("{0} : {1}\r\n", DateTime.Now, data)); 
} 

觀衆代碼:

int index = 0; 
private void Form1_Load(object sender, EventArgs e) 
     { 
      try 
      { 
       using (StreamReader sr = new StreamReader(logFilePath)) 
       { 
        while (sr.Peek() >= 0) // reading the old data 
        { 
         AddLineToGrid(sr.ReadLine()); 
         index++; 
        } 
        sr.Close(); 
       } 

       timer1.Start(); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 


private void timer1_Tick(object sender, EventArgs e) 
     { 
      using (StreamReader sr = new StreamReader(logFilePath)) 
      { 
       // skipping the old data, it has read in the Form1_Load event handler 
       for (int i = 0; i < index ; i++) 
        sr.ReadLine(); 

       while (sr.Peek() >= 0) // reading the live data if exists 
       { 
        string str = sr.ReadLine(); 
        if (str != null) 
        { 
         AddLineToGrid(str); 
         index++; 
        } 
       } 
       sr.Close(); 
      } 
     } 

是否有閱讀和寫作的方式在我的代碼什麼問題?

如何解決問題?

+0

可能的重複[可以阻止StreamReader鎖定正在使用的文本文件嗎?](https://stackoverflow.com/questions/1606349/can-i-prevent-a-streamreader-from-locking -a-text-file-while-it-in-use) – 2017-09-15 09:49:23

回答

94

您需要確保服務和閱讀器都非獨佔打開日誌文件。試試這個:

對於服務作爲創建FileStream實例如下:

var outStream = new FileStream(logfileName, FileMode.Open, 
           FileAccess.Write, FileShare.ReadWrite); 

對於讀者使用的相同,但更改文件權限:

var inStream = new FileStream(logfileName, FileMode.Open, 
           FileAccess.Read, FileShare.ReadWrite); 

祝你好運!

+0

還有ReadLines()版本在http://stackoverflow.com/questions/5338450/file-readlines-without-locking-it – Colin 2013-11-13 01:22:21

+0

完美 - 我以爲File.Open()與FileAccess.Read就夠了,但它不是。不過,這是。 :) – neminem 2017-09-12 00:23:26

2

您是否嘗試過複製文件,然後閱讀它?

只要進行大的更改就更新副本。

+1

我試過這個,它不是最好的解決方案。複製文件需要很長時間,因爲4mb文件需要20秒。 – Seichi 2015-05-25 14:48:38

6

問題是,當您寫入日誌時,您將專門鎖定文件,因此您的StreamReader將不被允許打開它。

您需要嘗試打開文件只讀模式。

using (FileStream fs = new FileStream("myLogFile.txt", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) 
{ 
    using (StreamReader sr = new StreamReader(fs)) 
    { 
     while (!fs.EndOfStream) 
     { 
      string line = fs.ReadLine(); 
      // Your code here 
     } 
    } 
} 
+0

現在我知道,'File.ReadAllText()'以只讀模式失敗。 – 2013-10-17 14:27:15

+0

@modosansreves是的我刪除了[文檔](http://msdn.microsoft.com/en-us/library/ms143368(v = vs.100).aspx)答案的部分,它會拋出一個如果文件是隻讀文件,則'UnauthorizedAccessException' - 在應答時必須錯過! – James 2013-10-17 14:33:04

26

在讀取文本文件時顯式設置共享模式。

using (FileStream fs = new FileStream(logFilePath, 
             FileMode.Open, 
             FileAccess.Read,  
             FileShare.ReadWrite)) 
{ 
    using (StreamReader sr = new StreamReader(fs)) 
    { 
     while (sr.Peek() >= 0) // reading the old data 
     { 
      AddLineToGrid(sr.ReadLine()); 
      index++; 
     } 
    } 
} 
+2

由於StreamReader.Dispose會自動關閉流,因此不必顯式關閉流。 – nothrow 2010-08-10 11:16:26

+2

我相信文件共享應該設置在讀寫流上,而不是隻讀。 – 2010-08-10 11:19:41

10
new StreamReader(File.Open(logFilePath, 
          FileMode.Open, 
          FileAccess.Read, 
          FileShare.ReadWrite)) 

- >這不鎖定文件。

+0

似乎在讀取數據時工作。寫入鎖定文件時出現錯誤。 – webzy 2016-02-08 09:00:20

5

我記得幾年前做同樣的事情。經過一些谷歌查詢,我發現這個:

FileStream fs = new FileStream(@」c:\test.txt」, 
            FileMode.Open, 
            FileAccess.Read,   
            FileShare.ReadWrite); 

即使用FileStream()FileShare.ReadWrite屬性。

(上Balaji Ramesh's blog找到)

0

這種方法將幫助你最快的讀取一個文本文件,而無需將其鎖定。

private string ReadFileAndFetchStringInSingleLine(string file) 
    { 
     StringBuilder sb; 
     try 
     { 
      sb = new StringBuilder(); 
      using (FileStream fs = File.Open(file, FileMode.Open)) 
      { 
       using (BufferedStream bs = new BufferedStream(fs)) 
       { 
        using (StreamReader sr = new StreamReader(bs)) 
        { 
         string str; 
         while ((str = sr.ReadLine()) != null) 
         { 
          sb.Append(str); 
         } 
        } 
       } 
      } 
      return sb.ToString(); 
     } 
     catch (Exception ex) 
     { 
      return ""; 
     } 
    } 

希望這種方法能幫助你。

相關問題