2012-04-02 49 views
4

我的應用程序緩慢地讀取一個浮點數的TextFile。情況會不時發生變化,文件必須重寫。一些示例代碼:如何編寫正在讀取的文件?

procedure TAMI_Column_Selector.read_continuously (file_name: string); 
var infile: TextFile; 
    f: Double; 
begin 
    AssignFile (infile, file_name); 
    Reset (infile); 
    try 
     while not EOF (infile) do 
     begin 
     Read (infile, f); 
     process (f); // this may take quite some time, seconds or even minutes 
     end; // while 
    finally 
     CloseFile (infile); 
    end; // try..finally 
end; // read_continuously // 

如何編寫一個可以閱讀的文件?更具體地說:

  1. 我該怎麼寫一個可以閱讀的文件?
  2. 如何防止應用程序試圖讀取當時正在編寫 的文件時發生崩潰
  3. 我的應用程序如何知道文件已被重寫?

我認爲我可以解決第一個問題,即將文件讀入內存並讀取該文件(是否存在可以寫入和讀取內存的TextFile)?然後,我仍然可以測試一個已經寫好的文件。

任何人有一個(優雅)解決這個問題?

在此先感謝。

在Windows 7

+1

讓你的閱讀程序對不完整閱讀有魯棒性。然後使用現代IO(即'TFileStream')而不是Pascal IO。爲您的作家打開文件時指定'fmShareDenyWrite'。爲您的讀者指定'fmShareDenyNone'。或者,使用數據庫! – 2012-04-02 20:07:46

+0

我描述的情況是一個導入設施,所以我使用csv文件。數據庫可以解決所有問題,但在這種情況下不可行。 – Arnold 2012-04-03 04:59:06

回答

4

用Delphi XE要寫入的文件也是開放的閱讀,有一般不會有什麼特別的作家需要做。如果打開文件的其他人都有允許寫入文件,則預期的作者可以打開文件進行寫入,寫入文件並關閉文件。如果其他沒有允許寫入該文件,那麼預期的作者將不被允許首先打開該文件,並且對此無能爲力。

如何打開文件進行閱讀同時也允許寫入取決於正在使用的打開方法。使用CreateFiledwDesiredAccess參數是通常的GENERIC_READ,並且dwShareMode參數是FILE_SHARE_READ or FILE_SHARE_WRITE。如果您使用的是TFileStream,則構造函數的模式參數應爲fmOpenWrite or fmShareDenyNone。如果您使用的是AssignFileReset,那麼您需要設置FileMode全局變量,但不支持任何共享模式,因此您不能使用Pascal樣式的I/O。

讀取同時寫入的文件本身不會導致崩潰。它當然不會在操作系統級別造成問題。如果你的程序崩潰了,那是因爲它沒有被寫入來預測讀取失敗。當您閱讀某些內容時,請檢查API結果以確認您讀取的字節數與您請求的一樣多。您還可以讓讀寫應用程序相互通信。您可能使用同步對象來序列化對文件的訪問,或者寫入者可能會向讀者發送一個信號來指示該文件已更改,並且之前的讀取可能不再準確。工作細節由你決定。

如果讀者要在內存中保存文件的副本,那麼它可能不需要打擾共享寫入訪問。相反,它可以打開文件並僅共享讀取訪問權限,在內存中創建該文件的副本,然後關閉文件。然後,作者可以打開文件,而不用擔心踐踏讀者流程,因爲沒有什麼可踐踏的。它可以通知讀者更改了某些內容,讀者可以重新加載整個文件或只加載更改的部分。 (雖然作者不得不告訴讀者哪部分已經改變,但沒有其他方式可以讓讀者在沒有讀取整個文件的情況下檢測到它與存儲器副本的差異)。

保持寫入的另一種方法從干擾讀取是使用交易。儘管如此,Transactional NTFS正在被逐步淘汰。微軟已經發布了a list of alternatives,所以你可以嘗試找到符合你需求的東西。

+0

非常感謝你爲這個精心設計的答案。我認爲它回答了我應該避免的所有陷阱。還有一件事我還不知道,我怎麼知道文件已被重寫? – Arnold 2012-04-03 04:56:34

+0

我應該更準確地說出問題3。我的意思是我如何檢測正在被另一個應用程序修改的文件。我將第3段視爲解釋檢測解釋中的變化。如果有更多的意圖,我不知道該怎麼做。 – Arnold 2012-04-12 13:53:27

+0

這一直是我的假設:一個或多個過程正在閱讀,另外一個或多個正在寫作。一個進程知道另一個進程修改文件的確定的方法是讓另一個進程*告訴它它已經完成了;這就是我的第三段的第二部分。您還可以嘗試使用['ReadDirectoryChangesW'](http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa365465.aspx)檢測目錄中的文件是否更改了大小或最後寫入時間。 – 2012-04-12 15:25:15