詳解C#如何監(jiān)控選定文件夾中文件的變動(dòng)情況
前言
有時(shí)候我們會(huì)有監(jiān)控電腦上某一個(gè)文件夾中文件變動(dòng)情況的需求,在本文中,我也會(huì)以一個(gè)具體的例子,說明在C#中如何使用FileSystemWatcher類來實(shí)現(xiàn)上述需求。
效果


具體實(shí)現(xiàn)
如果你對(duì)C#如何監(jiān)控選定文件夾中文件的變動(dòng)情況感興趣,可以繼續(xù)往下閱讀。
界面設(shè)計(jì)
為了更好的演示效果,我這里winform的界面設(shè)計(jì)如下:

很簡(jiǎn)單,只有一個(gè)button與一個(gè)richtextbox,button用來指定被監(jiān)控的文件,richtextbox用來輸出一些信息。
全部代碼
namespace FileSystemWatcherDemo
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
?
private void button1_Click(object sender, EventArgs e)
{
?
// 創(chuàng)建一個(gè) FolderBrowserDialog 實(shí)例
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
?
// 設(shè)置對(duì)話框的標(biāo)題
folderBrowserDialog.Description = "選擇文件夾";
?
// 如果用戶點(diǎn)擊了“確定”按鈕
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
richTextBox1.Text = "";
// 獲取用戶選擇的文件夾路徑
string selectedFolder = folderBrowserDialog.SelectedPath;
?
// 提示被監(jiān)控文件夾路徑
richTextBox1.Text += $"被監(jiān)控的文件夾為:{selectedFolder}\r\n";
?
var watcher = new FileSystemWatcher($"{selectedFolder}");
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
?
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
watcher.Deleted += OnDeleted;
watcher.Renamed += OnRenamed;
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
else
{
MessageBox.Show("您本次沒有選擇文件夾?。。?);
}
?
}
?
private void AppendMessageToRichTextBox(string message)
{
// 在RichTextBox中添加提示信息
richTextBox1.Invoke(new Action(() =>
{
richTextBox1.AppendText(message + Environment.NewLine);
}));
}
?
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
AppendMessageToRichTextBox($"Changed: {e.FullPath}");
}
?
private void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
AppendMessageToRichTextBox($"Created: {e.FullPath}");
}
?
private void OnDeleted(object sender, FileSystemEventArgs e)
{
AppendMessageToRichTextBox($"Deleted: {e.FullPath}");
}
?
private void OnRenamed(object sender, RenamedEventArgs e)
{
AppendMessageToRichTextBox($"Renamed:");
AppendMessageToRichTextBox($" Old: {e.OldFullPath}");
AppendMessageToRichTextBox($" New: {e.FullPath} ");
}
}
}
FileSystemWatcher的介紹
看過以上代碼,會(huì)發(fā)現(xiàn)核心就是FileSystemWatcher的使用。接下來我將介紹一下C#中的FileSystemWatcher類。
FileSystemWatcher是C#中的一個(gè)類,該類可以偵聽文件系統(tǒng)更改通知,并在目錄或目錄中的文件發(fā)生更改時(shí)引發(fā)事件。
FileSystemWatcher的構(gòu)造函數(shù)
該類有三種構(gòu)造函數(shù),如下所示:
| 形式 | 含義 |
|---|---|
| FileSystemWatcher() | 初始化 FileSystemWatcher 類的新實(shí)例。 |
| FileSystemWatcher(String) | 初始化 FileSystemWatcher 類的新實(shí)例,給定要監(jiān)視的目錄。 |
| FileSystemWatcher(String, String) | 初始化 FileSystemWatcher類的新實(shí)例,給定要監(jiān)視的目錄和文件類型。 |
var watcher = new FileSystemWatcher($"{selectedFolder}");
本文中我選擇的就是第二種構(gòu)造函數(shù),指定要監(jiān)視的目錄。
FileSystemWatcher的屬性
現(xiàn)在介紹一下在本示例中用到的FileSystemWatcher的屬性,如下所示:
| 名稱 | 類型 | 含義 |
|---|---|---|
| EnableRaisingEvents | bool | 設(shè)置FileSystemWatcher是否有效 |
| Filter | string | 設(shè)置一個(gè)要監(jiān)控的文件的格式 |
| Filters | Collection | 設(shè)置多個(gè)要監(jiān)控的文件的格式 |
| IncludeSubdirectories | bool | 獲取或設(shè)置一個(gè)值,該值指示是否應(yīng)監(jiān)視指定路徑中的子目錄 |
| NotifyFilter | NotifyFilters | 獲取或設(shè)置要監(jiān)視的更改的類型 |
| Path | string | 獲取或設(shè)置要監(jiān)視的目錄的路徑 |
現(xiàn)在來解釋下所用到的代碼的含義:
watcher.Filter = "*.txt";
表示要監(jiān)控的文件為.txt格式。
watcher.IncludeSubdirectories = true;
表示指定路徑中的子目錄也要監(jiān)視。
watcher.EnableRaisingEvents = true;
表示該對(duì)象可以觸發(fā)事件,也就是還有效。
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
設(shè)置要監(jiān)視的更改的類型。NotifyFilter屬性的類型為NotifyFilters枚舉類型。
NotifyFilters枚舉類型:
[System.Flags] public enum NotifyFilters
指定要在文件或文件夾中監(jiān)視的更改。
此枚舉支持其成員值的按位組合。
該枚舉類型包含的值與含義如下所示:
| 名稱 | 含義 |
|---|---|
| Attributes | 文件或文件夾的屬性 |
| CreationTime | 文件或文件夾的創(chuàng)建時(shí)間 |
| DirectoryName | 目錄名 |
| FileName | 文件的名稱 |
| LastAccess | 文件或文件夾上一次打開的日期 |
| LastWrite | 上一次向文件或文件夾寫入內(nèi)容的日期 |
| Security | 文件或文件夾的安全設(shè)置 |
| Size | 文件或文件夾的大小 |
在這里使用了該枚舉類型的按位組合表示這幾種更改的類型要受到監(jiān)視。
FileSystemWatcher的事件
FileSystemWatcher中的事件如下:
| 名稱 | 含義 |
|---|---|
| Changed | 當(dāng)更改指定 Path 中的文件和目錄時(shí)發(fā)生 |
| Created | 當(dāng)在指定Path 中創(chuàng)建文件和目錄時(shí)發(fā)生 |
| Deleted | 刪除指定Path中的文件或目錄時(shí)發(fā)生 |
| Renamed | 重命名指定 Path中的文件或目錄時(shí)發(fā)生 |
| Error | 當(dāng) FileSystemWatcher 的實(shí)例無法繼續(xù)監(jiān)視更改或內(nèi)部緩沖區(qū)溢出時(shí)發(fā)生 |
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
watcher.Deleted += OnDeleted;
watcher.Renamed += OnRenamed;
在這里我使用到了Changed、Created、Deleted和Renamed事件。
我將以Changed 事件為例,詳細(xì)解釋一下:
watcher.Changed += OnChanged;
這行代碼的含義。
我們查看FileSystemWatcher的源代碼,Changed事件的代碼如下所示
可知將值賦給了_onChangedHandler,我們?cè)賮聿榭?code>_onChangedHandler的定義:
/// <devdoc>
/// Occurs when a file or directory in the specified <see cref='System.IO.FileSystemWatcher.Path'/> is changed.
/// </devdoc>
public event FileSystemEventHandler? Changed
{
add
{
_onChangedHandler += value;
}
remove
{
_onChangedHandler -= value;
}
}
類型為FileSystemEventHandler?與Changed事件一致,再來看看FileSystemEventHandler?的定義:
public delegate void FileSystemEventHandler(object sender, FileSystemEventArgs e);
發(fā)現(xiàn)是一個(gè)參數(shù)類型分別為object、FileSystemEventArgs返回值類型為空的委托類型。
object我們知道,那么FileSystemEventArgs又是什么呢?
查看它的源碼,截取一部分,如下所示:
public class FileSystemEventArgs : EventArgs
{
private readonly WatcherChangeTypes _changeType;
private readonly string? _name;
private readonly string _fullPath;
/// <devdoc>
/// Gets one of the <see cref='System.IO.WatcherChangeTypes'/> values.
/// </devdoc>
public WatcherChangeTypes ChangeType
{
get
{
return _changeType;
}
}
?
/// <devdoc>
/// Gets the fully qualified path of the affected file or directory.
/// </devdoc>
public string FullPath
{
get
{
return _fullPath;
}
}
?
?
/// <devdoc>
/// Gets the name of the affected file or directory.
/// </devdoc>
public string? Name
{
get
{
return _name;
}
}
}
發(fā)現(xiàn)FileSystemEventArgs繼承自EventArgs,而EventArgs表示包含事件數(shù)據(jù)的類的基類,因此可以明白FileSystemEventArgs表示為目錄事件:Changed, Created, Deleted提供數(shù)據(jù)的類。
FileSystemEventArgs提供三個(gè)數(shù)據(jù)分別為ChangeType、FullPath、Name。
那ChangeType是什么呢?
查看ChangeType的定義:
//
// 摘要:
// Changes that might occur to a file or directory.
[Flags]
public enum WatcherChangeTypes
{
//
// 摘要:
// The creation of a file or folder.
Created = 1,
//
// 摘要:
// The deletion of a file or folder.
Deleted = 2,
//
// 摘要:
// The change of a file or folder. The types of changes include: changes to size,
// attributes, security settings, last write, and last access time.
Changed = 4,
//
// 摘要:
// The renaming of a file or folder.
Renamed = 8,
//
// 摘要:
// The creation, deletion, change, or renaming of a file or folder.
All = 15
}
是一個(gè)枚舉類型,表示更改的類型。
現(xiàn)在回過頭來看:
watcher.Changed += OnChanged;
OnChanged方法如下:
private void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
AppendMessageToRichTextBox($"Changed: {e.FullPath}");
}
為什么可以將OnChanged方法訂閱到watcher.Changed事件上呢?
因?yàn)镺nChanged方法與watcher.Changed事件中的委托類型FileSystemEventHandler的返回類型和簽名是相同的。
OnChanged方法的返回類型與簽名如下:
private void OnChanged(object sender, FileSystemEventArgs e)
FileSystemEventHandler委托類型的定義如下:
public delegate void FileSystemEventHandler(object sender, FileSystemEventArgs e);
現(xiàn)在已經(jīng)理解了訂閱事件,那么什么時(shí)候觸發(fā)事件呢?
查看FileSystemWatcher的部分源碼:
/// <devdoc>
/// Raises the <see cref='System.IO.FileSystemWatcher.Changed'/> event.
/// </devdoc>
protected void OnChanged(FileSystemEventArgs e)
{
InvokeOn(e, _onChangedHandler);
}
private void InvokeOn(FileSystemEventArgs e, FileSystemEventHandler? handler)
{
if (handler != null)
{
ISynchronizeInvoke? syncObj = SynchronizingObject;
if (syncObj != null && syncObj.InvokeRequired)
syncObj.BeginInvoke(handler, new object[] { this, e });
else
handler(this, e);
}
}
當(dāng)發(fā)生相應(yīng)的改變時(shí),就會(huì)調(diào)用FileSystemWatcher類的OnChanged方法,從而觸發(fā)事件。
以上就是詳解C#如何監(jiān)控選定文件夾中文件的變動(dòng)情況的詳細(xì)內(nèi)容,更多關(guān)于C#監(jiān)控文件的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C# WPF 通過委托實(shí)現(xiàn)多窗口間的傳值的方法
這篇文章主要介紹了C# WPF 通過委托實(shí)現(xiàn)多窗口間的傳值的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
C# Distinct和重寫IEqualityComparer時(shí)要知道的二三事
這篇文章主要給大家介紹了關(guān)于C# Distinct和重寫IEqualityComparer時(shí)要知道的二三事,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Unity中的靜態(tài)批處理和動(dòng)態(tài)批處理操作
這篇文章主要介紹了Unity中的靜態(tài)批處理和動(dòng)態(tài)批處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04
C#利用RabbitMQ實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)消息傳輸
RabbitMQ做為消息代理,負(fù)責(zé)接收和轉(zhuǎn)發(fā)消息,可以將RabbitMQ比喻為一個(gè)郵筒、一個(gè)郵局和一個(gè)郵遞員。本文主要以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述RabbitMQ實(shí)現(xiàn)消息傳輸?shù)南嚓P(guān)內(nèi)容,僅供學(xué)習(xí)分享使用,如有不足之處,還請(qǐng)指正。2021-05-05
解析C#中委托的同步調(diào)用與異步調(diào)用(實(shí)例詳解)
本篇文章是對(duì)C#中委托的同步調(diào)用與異步調(diào)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
C#實(shí)現(xiàn)設(shè)置或屏蔽熱鍵的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用C#實(shí)現(xiàn)設(shè)置或屏蔽熱鍵,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C#有一定的幫助,感興趣的小伙伴可以跟隨小編一起了解一下2022-12-12
C#實(shí)現(xiàn)人臉識(shí)別超簡(jiǎn)單方法舉例
這篇文章主要給大家介紹了關(guān)于C#實(shí)現(xiàn)人臉識(shí)別的相關(guān)資料,文中講解了在C#中使用EmguCV庫進(jìn)行人臉識(shí)別的簡(jiǎn)單示例,包括安裝EmguCV庫、準(zhǔn)備訓(xùn)練數(shù)據(jù)、編寫代碼和運(yùn)行程序,需要的朋友可以參考下2024-11-11

