2010-01-29 46 views
2

我工作的一個應用程序,將讓工作運行指數造詣。改寫快速連續相同的文件?

可以在工作會議結束時寫一次,但是我不想冒險失去數據,如果事情炸燬。因此,我重寫到磁盤(XML),每一個新的條目或修訂是由用戶製作時間。

private void WriteIndexFile() 
{ 
    XmlDocument IndexDoc 
    // Build document here 

    XmlTextWriter tw = new XmlTextWriter(_filePath, Encoding.UTF8); 
    tw.Formatting = Formatting.Indented; 
    IndexDoc.Save(tw); 
} 

有可能快速連續觸發寫操作。如果發生這種情況,它會嘗試打開該文件編寫前先寫操作完成。 (雖然它不會是正常的,我想這是可能的文件被打開,以供其他程序。)

我如何檢查文件是否可以重新寫的?

編輯澄清:這是自動化實驗室數據收集系統的一部分。用戶將點擊一個按鈕來捕獲數據(保存在單獨的文件中),並確定數據包的子任務。通常,點擊之間的時間爲3-10分鐘。

如果他們做出了錯誤,他們需要能夠回去並糾正它,所以它不是一個只追加使用率。

最後,該文件會被其他的自動化工具和手動人類閱讀。 (XML/XSLT)

尺寸會受到限制,因爲每個工作會議(工人移位或更小)將具有產生新的索引文件。

進一步的問題:作爲壓倒性的共識是不使用XML,並在僅附加模式寫,我會怎麼解決回去和糾正早期項目的要求?

我正在考慮有一個「髒」標誌,標誌設置後保存幾分鐘後關閉工作會議。如果在此期間發生多個編輯,則只會發生一次寫入 - 沒有更快的用戶 - 如果保存失敗,也會有重試/取消對話框。思考?

+0

當寫入失敗時你打算做什麼?向用戶報告並撤消?沒有寫會阻礙你繼續下去? – 2010-01-29 21:09:18

+0

@Moron:這確實是主要問題。如果失敗可以從優雅地恢復並且寫作恢復,那麼它是可以的。如果故障無法恢復(即某些其他未知應用將文件或磁盤鎖定爲已滿),則繼續丟失數據將是一種損失。 也許重試/取消對話框...? – mbmcavoy 2010-01-29 21:59:50

回答

1

如果你想要的是所有操作的一個簡單的日誌,XML可以在這裏是錯誤的選擇,因爲它是難以追加到XML文檔而無需重寫整個文件,因爲文件的增長,這將成爲越來越慢。

我建議改爲File.AppendText,甚至更好:在應用程序的使用期限內保持文件打開並使用WriteLine

(呵呵,正如其他人所指出的那樣,你需要lock,以確保只有一個線程在同一時間寫入文件。這仍然是真實的,即使這個解決方案。)

還有一些記錄已經解決了這個問題的框架,比如log4net。你有沒有考慮過使用現有的日誌框架,而不是滾動自己的?

+0

也許他的PHB說它*必須*用XML。是的,XML是這項工作的錯誤工具,但是XML對許多工作來說都是錯誤的工具,它仍然在使用。有時尖括號會讓我哭泣。 :'( – dss539 2010-01-29 21:13:05

+0

)並非所有更改都是簡單附加,它基於用戶輸入,用戶需要能夠返回並更正錯誤。另外,有些屬性可能會隨着事情的進展而改變。 該文件需要「漂亮「超鏈接和其他進程的機器可讀性 - 選擇XML/XSLT的解決方案 最後,我並不太擔心大小/寫入性能 - 一個新文件將會頻繁啓動,我期望每一個最大〜50KB。 – mbmcavoy 2010-01-29 21:26:27

4

XML是你的情況糟糕的選擇,因爲新的內容,以結束標記之前插入。使用文本istead,只需打開文件追加並在文件末尾寫入新內容,請參閱How to: Open and Append to a Log File

您也可以考慮像log4net一個簡單的日誌框架並使用,而不是處理低級文件的東西urself。

0

我有一個記錄器,使用System.Collections.Queue。基本上它會等待,直到排隊,然後再寫入它。在寫入項目時,速度可能很慢,可以將更多項目添加到隊列中。

這也有助於將消息分組,而不是試圖跟上。它在單獨的線程上運行。

private AutoResetEvent ResetEvent { get; set; } 

LogMessage(string fullMessage) 
{ 
    this.logQueue.Enqueue(fullMessage); 

    // Trigger the Reset Event to send the 
    this.ResetEvent.Set(); 
} 

private void ProcessQueueMessages() 
{ 
    while (this.Running) 
    { 
     // This will process all the items in the queue. 
     while (this.logQueue.Count > 0) 
     { 
      // This method will just log the top item on the queue 
      this.LogQueueItem(); 
     } 

     // Once the queue is empty will wait for a 
      // another message to queueed before running again. 
     // Rather than sleeping and checking if the queue is full, 
      // saves from doing a System.Threading.Thread.Sleep(1000); stuff 
     this.ResetEvent.WaitOne(); 
    } 
} 

我處理寫入失敗但沒有出隊,直到寫入文件沒有錯誤。然後我只是不停地嘗試,直到它終於寫出來。這節省了我,因爲有人在我們的應用程序中刪除了其中一個應用程序的權限。我們的應用程序關閉了權限,並且我們沒有丟失單個日誌語句。

0

考慮使用平面文本文件。我有一個使用XML日誌編寫的進程......這是一個糟糕的選擇。您無需在運行時直接寫出狀態,而無需不斷重寫文件以確保標籤正確。如果它是寫入文件的平面條目,那麼您可以使用自動時間軸,可以讓您知道發生了什麼情況的詳細信息,而無需弄清楚它是否是XML寫入器/標記集發生爆炸,而且您不必擔心自己的問題日誌一樣膨脹。

0

我同意他人建議您避免使用XML。另外,我建議你有一個組件(一個「監視器」)負責所有的文件訪問。該組件將具有處理多個同時請求並使磁盤寫入一個接一個地發生的工作。