實現文件實時讀取與監控的方法


 

1、文件實時寫入

    最近需要為實驗室寫一個監控文本數據並實時讀取繪制曲線的小程序,原軟件從串口接收傳感器的數據,實時寫入txt文本,現在需要寫個程序實時讀取出來,遇到一個問題:原軟件有個文本框實時顯示數據,查看源代碼發現文本框顯示和寫入文本是同時完成的,但是文件寫入卻有延遲,有時候過去很長時間重新打開文本文件,內容都不發生改變。每次文本容量增加512字節內容才發生變化,這樣就導致無法對該文件進行實時讀取和監控,找了很多資料,發現這樣一段話:  

”在PC硬件體系結構里,速度最快的存儲器是CPU里面的寄存器,接着到二級緩存,再到系統RAM內存,最后才到硬盤。由於這樣的體系結構,就決定了操作系統對文件的操作方式,或者說是最優化的算法。比如操作系統接收到寫文件的數據時,就會先把數據保存到RAM里,然后在合適的時間或者合適的數據量時再寫到硬盤里。但有時候我們希望數據一定要保存到硬盤里,而不是保存在RAM里,這時就需要使用函數FlushFileBuffers來把RAM里的數據保存到硬盤里。”

於是修改原軟件的源代碼(VB):

Private Declare Function FlushFileBuffers Lib "kernel32" (ByVal hFile As Long) As Long  

'創建文件

strTFile=path//路徑

hTFile = FreeFile
Open strTFile For Append As hTFile

 

'此處為strOut內容寫入

Print #hTFile, strTOut
FlushFileBuffers (hTFile)

這樣修改后,還是沒達到目的。在另一網頁上看到一個建議是需要當寫入文件完成后需要及時閉。因此在每次打開文件之后增加了如下關閉文件的代碼:

Close hTFile '關閉文件

果然文件實現了實時的寫入,不過這樣性能肯定下降,由於寫入頻率不快,在可接受范圍,就沒對性能進行分析。接下來測試下FlushFileBuffers函數有沒有發揮作用,刪去該函數,發現文件仍然實時寫入,因此,文件 open、Print,再Close文件之后,就可以實時將數據寫到磁盤的文件系統上,FlushFileBuffers 函數並不能實時寫磁盤!

2、文件的實時讀取

監控小程序采用C#編寫,采用 FileStream和StreamReader實時讀取文本文件。采用如下代碼:

FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read);
StreamReader sr = new StreamReader(fs, Encoding.Default);

這里出現一個問題,提示:

解決辦法是:采用共享讀寫方式,就沒問題

FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
StreamReader sr = new StreamReader(fs, Encoding.Default);

 

3、文件的實時監控

實踐中用了兩種辦法(取一):

(1) 采用timer計時器,每個一定間隔分別對該文件的大小進行計算,當發生改變時,觸發事件

private void button3_Click(object sender, EventArgs e)
{
timer1.Interval = 500;
timer1.Enabled = true;
timer1.Start();
}

private void timer1_Tick(object sender, EventArgs e)
{
if (foldPath == "" || file == "") return;
FileInfo fi = new FileInfo(foldPath + "//" + file);
fi.Refresh();

Int64 size = fi.Length;

textBox3.Text = size.ToString();//實時顯示文件字節數
}

(2)第二中辦法是,采用 FileSystemWatcher類,如下:

//監控函數
private void startWatch()
{
if (foldPath == "" || file == "") return;
watch = new FileSystemWatcher();
this.watch.Changed += new FileSystemEventHandler(File_changed);//注冊事件


this.watch.Path = @foldPath;//監視的目錄
this.watch.Filter = file;//監視的文件
this.watch.IncludeSubdirectories = false;//不監視子目錄
this.watch.EnableRaisingEvents = true;//開始監控
}
int sun = 0;
//文件有修改引發的事件
private void File_changed(object sender, FileSystemEventArgs e)
{

if (e.FullPath ==foldPath+"\\"+ file)
{
//監視到文件被修改
sun = sun + 1;//統計改變的次數


}

}

 

//End

 

參考文章:1、http://bbs.csdn.net/topics/350041265

              2、http://blog.csdn.net/caimouse/article/details/1837984

              3、http://blog.csdn.net/wangbaochu/article/details/44305591

              4、http://bbs.bccn.net/thread-350527-1-1.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM