2008-09-17 49 views
3

我有一個經常更新(每分鐘約20至30次)的.csv文件。我想在寫入文件後立即將新添加的行插入到數據庫中。使用.NET實時讀取文件中的更改內容

FileSystemWatcher類監聽文件系統更改通知,並可以在指定文件發生更改時引發事件。問題是FileSystemWatcher無法確定哪些行被添加或刪除(據我所知)。

讀取這些行的一種方法是保存並比較更改之間的行數,並讀取最後一次和最後一次更改之間的差異。不過,我正在尋找更清潔(也許更優雅)的解決方案。

回答

3

我寫了一些非常相似的東西。我使用FileSystemWatcher來獲取有關更改的通知。然後,我使用FileStream讀取數據(跟蹤文件中的最後位置,並在讀取新數據之前查找數據)。然後我將讀取的數據添加到一個緩衝區,該緩衝區會自動提取完整的行,然後輸出到UI。

注:「this.MoreData(..)是一個事件,聽者其中增加了上述緩衝區,並處理完整的線條提取

注:正如已經提到的,這隻會工作如果修改總是添加到文件。任何刪除將導致問題。

希望這可以幫助。

public void File_Changed(object source, FileSystemEventArgs e) 
    { 
     lock (this) 
     { 
      if (!this.bPaused) 
      { 
       bool bMoreData = false; 

       // Read from current seek position to end of file 
       byte[] bytesRead = new byte[this.iMaxBytes]; 
       FileStream fs = new FileStream(this.strFilename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); 

       if (0 == this.iPreviousSeekPos) 
       { 
        if (this.bReadFromStart) 
        { 
         if (null != this.BeginReadStart) 
         { 
          this.BeginReadStart(null, null); 
         } 
         this.bReadingFromStart = true; 
        } 
        else 
        { 
         if (fs.Length > this.iMaxBytes) 
         { 
          this.iPreviousSeekPos = fs.Length - this.iMaxBytes; 
         } 
        } 
       } 

       this.iPreviousSeekPos = (int)fs.Seek(this.iPreviousSeekPos, SeekOrigin.Begin); 
       int iNumBytes = fs.Read(bytesRead, 0, this.iMaxBytes); 
       this.iPreviousSeekPos += iNumBytes; 

       // If we haven't read all the data, then raise another event 
       if (this.iPreviousSeekPos < fs.Length) 
       { 
        bMoreData = true; 
       } 

       fs.Close(); 

       string strData = this.encoding.GetString(bytesRead); 
       this.MoreData(this, strData); 

       if (bMoreData) 
       { 
        File_Changed(null, null); 
       } 
       else 
       { 
        if (this.bReadingFromStart) 
        { 
         this.bReadingFromStart = false; 
         if (null != this.EndReadStart) 
         { 
          this.EndReadStart(null, null); 
         } 
        } 
       } 
      } 
     } 
+0

爲什麼downvote? – RichS 2014-11-05 11:54:23

0

關閉我的頭頂上,你可以存儲最後一個已知的文件大小。檢查文件大小,並在更改時打開閱讀器。

然後請讀者閱讀您的最後一個文件大小,並從那裏開始閱讀。

+0

只是因爲文件大小保持不變並不意味着沒有任何改變。哈希會更合適..或在這種情況下,使用FileSystemWatcher。 – mmcdole 2008-10-19 15:27:13

1

如果足夠小,我會將當前文本保留在內存中,然後使用diff算法檢查新文本和以前的文本是否更改。這個庫,http://www.mathertel.de/Diff/,不僅會告訴你有什麼改變,但改變了什麼。所以你可以將更改後的數據插入到數據庫中。

2

對,FileSystemWatcher不知道任何關於您文件內容的信息。它會告訴你它是否改變了,等等,但沒有改變。

你只是添加到文件?從帖子中可以看出,是否添加了線條或者是否可以刪除。假設他們被追加,解決方案非常簡單,否則你會做一些比較。

0

你說得對FileSystemWatcher。您可以偵聽創建,修改,刪除等事件,但不會比引發它們的文件更深入。

你有控制文件本身嗎?您可以稍微改變模型以像緩衝區一樣使用文件。有兩個,而不是一個文件。一個是分期,一個是所有已處理產出的總和。讀取「緩衝區」文件中的所有行,處理它們,然後將它們插入另一個文件的末尾,這是所有處理行的總數。然後,刪除你處理的行。這樣,文件中的所有信息都處於待處理狀態。問題在於,如果系統是寫入以外的東西(即也刪除行),那麼它將不起作用。

2

我認爲你應該使用NTFS更改日誌或類似:

更改日誌中使用NTFS來 提供對文件所做的捲上的所有 變化的持續日誌。 對於每個卷,NTFS使用更改 日誌到跟蹤信息約 添加,刪除和修改文件。 更改日誌更多 比時間戳或文件 有效確定給定名稱空間中的更改 的通知。

你可以找到一個description on TechNet。你將需要在.NET中使用PInvoke。