在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.IO 定义了一系列类、接口、枚举、结构和委托。
它们大多数包含在 mscorlib.dll! 另外有一部分部分 System.IO 命名空间的成员则包含在systcm.dll程序集中。
System.IO命名空间的多数类型主要用于编程操作物理目录和文件,而另一些类型则提供了从字符串缓冲区和内存区域中读写数据的方法。
下面是有关System.IO命名空间的主要成员
System.IO命名空间的主要成员 | |
非抽象I/O类类型 | 作用 |
BinaryReader和BinaryWriter | 这两个类型能够以二进制值存储和读取基本数据(整型,布尔型,字符串型和其他类型) |
BufferedStream | 这个类型为字节流提供了临时的存储空间,可以以以后提交 |
Directory和DirectoryInfo | 这两个类型用来操作计算机的目录结构。Directory 类型主要的功能通过静态方法实现。 DirectoryInfo 类创刚通过一个有效的时象引用来实现类似功能 |
DriveInfo | 提供计算机驱动器的详细信息 |
File 和 FlleInfo | 这两个类用来操作计算机上的一组文件。Fi1e类型主要的功能通过静态成员实现。FlleInfo类型则通过一个有效的对象引用来实现类似功能 |
FileStream | 这个类型实现文件随记访问(比如寻址能力)以字节流来表示教据 |
FileSystemWatcher | 这个类型监控对指定外部文件的更改 |
MemoryStream | 这个类型实现对内存(而不是物理文件)中存储的流教据的随机访问 |
Path | 这个类型对包含文件或目录路径信息的System.Stream类型执行操作。这些操作是与平台无关的 |
StreamWriter和StreamReader | 这两个类型用来在(从)文件中存储(获取)文本信息。不支持随机文件访问 |
StringWriter和StringReader | 和StreamWriter/StreamReader类型差不多.这两个类型同样同文本信息打交道,不同的是基层的存储器是字符串缓冲区而不是物理文件 |
Directory(Info)和File(Info) 类型 实现单个文件和计算机目录操作
一般说来, Fllelnfo 和DirectoryInfo 是获取文件或目录细节(如创建时间、读写能力等)更好的方式,因为它们的成员往往会返回强类型的对象。相反,Directory 和File类成员往往会返回简单字符串值而不是强类型对象。不过.这仅仅是一个准则。在很多情况下,你都可以使用 File/FileInfo或Directory/DirectoryInfo 完成相同的工作
Filesystemlnfo 抽象基类
DirectoryInfo 和 FlleInfo 类型实现了许多FilesystemInfo 抽象基类的行为。大部分 FllesystemInfo类成员的作用是用来获取指定文件或目录的一般特性(比如创建时间、各种特性等)。
FilesystemInfo 属性
FllesystemInfo 属性 | |
属性 | 作用 |
Attributes | 获取或设置与当前文件关联的特性.由 FlleAttrlbutes 枚举表示(例如.是只读、加密、隐藏或压缩文件或目录) |
CreationTime | 获取或设置当前文件或目录的创建时间 |
Exists | 用来判断指定文件或目录是否存在的值 |
Extension | 获取文件的扩展名 |
FullName | 获取目录或文件的完整路径 |
LastAccessTime | 获取或设置上次访问当前文件或目录的时间 |
LastWriteTime | 获取或设置上次写人当前文件或目录的时间 |
Name | Name 获取当前文件或目录的名称 |
FilesystemInfo 类型还定义了Delete()方法,该操作由派生类型从硬盘中删除指定文件或目录来实现。同样,在获取文件特性前使用Refresh()方法能确保当前文件(或目录)的统计信息是最新的。
使用Directoryinfo类型
DirectoryInfo类包含一组用来创建、移动,删除和枚举所有目录/子目录的成员
DirectoryInfo类型的主要成员 | |
成员 | 操作 |
Create()和CreateSubdirectory() | 按照路径名建立一个目录(或者一组子目录) |
Delete() | 删除一个目录和它的所有内容 |
GetDirectories() | 返回一个表示当前目录中所有子目录的DirectoryInfo对象数组 |
GetFiles() | 返回Filelnfo对象教组,表示指定目录下的一组文件 |
MoveTo() | 将一个目录及其内容移动到一个新的路径 |
Parent | 获取指定路径的父目录 |
Root | 获取路径的根部分 |
获取DirectoryInfo 的属性代码如下
DirectoryInfo dir1 = new DirectoryInfo("."); //绑定当前的应用程序目录 DirectoryInfo dir2 = new DirectoryInfo(@"D:\360Downloads");//使用存在的目录 //如果试图使用一个不存在的目录.系统会引发System.IO.DirectoryNOtFoundExceptlon 异常。因此,如果指定了一个尚未创建的目录的话,在对目录进行操作前首先需要调用Create()方法。 DirectoryInfo dir3 = new DirectoryInfo(@"D:\360Downloads\dir2"); dir3.Create(); Console.WriteLine("DirectoryInfo 主要成员的实现"); Console.WriteLine("FullName:{0}", dir3.FullName); Console.WriteLine("Name:{0}", dir3.Name); Console.WriteLine("Parent:{0}", dir3.Parent); Console.WriteLine("CreationTime:{0}", dir3.CreationTime); Console.WriteLine("Attributes:{0}", dir3.Attributes); Console.WriteLine("Root:{0}", dir3.Root);
使用DirectoryInfo 类型枚举出文件
DirectoryInfo dir = new DirectoryInfo(@"C:\Users\Public\Pictures"); FileInfo[] imageFiles = dir.GetFiles("*.jpg", SearchOption.AllDirectories); foreach (FileInfo f in imageFiles) { Console.WriteLine("********************"); Console.WriteLine("file Name:{0}", f.Name); Console.WriteLine("file Length:{0}", f.Length); Console.WriteLine("file CreationTime:{0}", f.CreationTime); Console.WriteLine("file Attributes:{0}", f.Attributes); Console.WriteLine("********************"); }
使用DirectoryInfo类型创建子目录
DirectoryInfo dir = new DirectoryInfo(@"D:\360Downloads\dir2"); dir.CreateSubdirectory("MyFolder"); //尽骨不一定要去捕获 CreateSubdirectory()方法的返回值,但是需要知道的是.如果执行成功.它会返回DirectoryInfo类型 DirectoryInfo dir1=dir.CreateSubdirectory(@"MyFolser2\Data"); Console.WriteLine("New Foloser:{0}",dir1);
使用Directory类型
Directory的静态成员实现了由DirectoryInfo定义的实例级成员的大部分功能。 Directory成员返回的是字符串数据而不是强类型的Filelnfo 和 DirectoryInfo对象。
获取此计算机上的逻辑驱动器代码如下:
string[] dives = Directory.GetLogicalDrives(); Console.WriteLine("Here are your drives:"); foreach (string s in dives) { Console.WriteLine("------->{0}", s); }
删除之前建立的目录代码如下
try { Directory.Delete(@"D:\360Downloads\dir2\MyFolser2\Data"); } catch (IOException e) { Console.WriteLine(e.Message); }
使用DriveInfo类类型
System.IO命名空间提供了一个叫做Drivelnfo的类。和Drivelnfo.GetLogicalDrivers()相似.Drlvelnfo.GetDrives()静态方法能获取计算机上驱动器的名字。然而和Drlvelnfo.GetDrives()不同,Drlvelnfo提供了许多其他的细节(比如驱动器类型、可用空间、卷标等)。
得到所有驱动器的信息代码如下
DriveInfo[] myDivers = DriveInfo.GetDrives(); foreach (DriveInfo d in myDivers) { Console.WriteLine("Name:{0}", d.Name); Console.WriteLine("Type:{0}", d.DriveType); //检查驱动器是否已经安装好 if (d.IsReady) { Console.WriteLine("Free space:{0}", d.TotalFreeSpace); Console.WriteLine("Format space:{0}", d.DriveFormat); Console.WriteLine("Lable space:{0}", d.VolumeLabel); } Console.WriteLine("***************************"); }
使用FileInfo类类型
FlleInfo 类能让我们获得硬盘上现有文件的详细信息(创建时间,大小、文件特性等),并帮助我们创建、复制、移动和删除除文件
删除FileInfo实例绑定的文件
FileInfo 核心成员 | |
成员 | 作用 |
AppendText() | 创建一个StreamWriter类型(后面会讨论),它用来向文件追加文本 |
CopyTo() | 将现有文件复制到新文件 |
Create() | 创建一个新文件并且返回一个FileStream类型(后面会讨论).通过它来和新创建的文件进行交互 |
CreateText() | 创建一个写入新文本文件的StreamWriter对象 |
Delete() | 删除FileInfo实例绑定的文件 |
Directory | 获取父目录的实例 |
DirectoryName | 获取父目录的完整路径 |
Length | 获取当前文件的大小 |
MoveTo() | 将指定文件移到新位置.井提供指定新文件名的选项 |
Name | 获取文件名 |
Open() | 用各种读/写访问权限和共享特权打开文件 |
OpenRead() | 创建只读FileStream对象 |
OpenText() | 创建从现有文本文件中读取教据的StreamReade(后面会讨论) |
OpenWrite() | 创建只写FileStream类型 |
注意,大部分FileInfo类的成员返回I/O相关的特定对象(Filestream和StreamWriter),让我们以不同格式从关联文件读或向关联文件写数据。
FileInfo.Create()的用法
FileInfo f = new FileInfo(@"D:\360Downloads\dir2\Test.txt");
FileStream fs = f.Create();
fs.Close();
需要注意的是,FlleInfo.Create()方法返一个FileStearm对象。FileStream能对基层的文件进行同步/异步的读写操作:需要知道的是,FileInfo.Create()返回的FileStream对象给所有的用户授予完全读写操作权限.
还要注意,在使用了当前FileStream对象之后.要确保关闭句柄来释放流的底层非托管资源。由于FileStream实现了IDisposable,所以我们可以使用C#的using域来让编译器生成释放逻辑
FileInfo f1 = new FileInfo(@"D:\360Downloads\dir2\Test2.txt"); using (FileStream f2=f1.Create()) { }
FileInfo.Open() 方法
我们能使用FileInfo.Open()方法来打开现有文件.同时也能使用它来创建新文件,它比FileInfo.Create()多了很多细竹.因为open()通常有好几个参数,可以限定所操作的文件的整体结构。一旦调用open()完成后.它返回一个FileStream对象。
FileInfo f = new FileInfo(@"D:\360Downloads\dir2\Test3.txt"); using (FileStream fs = f.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { }
* 上面的重载 OPen()方法需要3个参数。
* 第一个参数指定I/O请求的基本方式(比如说新建文件、打开现有文件和追加文件等),它的值由FileMode
* 第二个参数的值由FileAccess枚举定义,用来决定基层流的读写行为
* 第三个参数FileShare指定文件在其他文件处理程序中的共享方式。
FileInfo.OpenRead() 和FileInfo.OpenWrite()
FileInfo.Open()方法能让我们用非常灵活的方式获取文件句柄,FileInfo类同样提供了OpenRead()和OpenWrite()成员。这些方法不需要提供各种枚举值.就能返回一个正确配置的只读或只写的FileStream类型。 OPenRead()和OPenWrite()也都返回一个FileStream对象
FileInfo f = new FileInfo(@"D:\360Downloads\dir2\test.txt"); using (FileStream fs = f.OpenRead()) { Console.WriteLine("ok"); } FileInfo f4 = new FileInfo(@"D:\360Downloads\dir2\test4.txt"); using (FileStream fs1 = f4.OpenWrite()) { }
FileInfo.OpenText()
OpenText()方法返回的是一个StreamReader类型(而不是不是FileStream类型)的实例。
FileInfo f = new FileInfo(@"D:\360Downloads\dir2\Test3.txt"); using (StreamReader reader = f.OpenText()) { }
FileInfo.CreateText() 和 FileInfo.AppendText()
FileInfo.CreateText() 和 FileInfo.AppendText()都返回的是一个StreamWriter类型
FileInfo f = new FileInfo(@"D:\360Downloads\dir2\Test6.txt"); using (StreamWriter sr = f.CreateText()) { } FileInfo f1 = new FileInfo(@"D:\360Downloads\dir2\aa.txt"); using (StreamWriter sr = f1.AppendText()) { }
使用 File类型
Flle类型的静态成员提供了和FileInfo类型差不多的功能。与FileInfo类似,File类提供了
AppendText(),create ()、 createText ()、 open()、 OPenRead ()、 openWrite()和 OpenText()方法。在大多数情况下,File 和 FileInfo 类型能互换使用。
using (FileStream fs = File.Create(@"D:\360Downloads\dir2\bb.txt")) { } using (FileStream fs = File.Open(@"D:\360Downloads\dir2\bb.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { } using (FileStream fs = File.OpenRead(@"D:\360Downloads\dir2\bb.txt")) { } using (FileStream fs = File.OpenWrite(@"D:\360Downloads\dir2\bb.txt")) { } using (StreamReader sr = File.OpenText(@"D:\360Downloads\dir2\bb.txt")) { } using (StreamWriter sw = File.CreateText(@"D:\360Downloads\dir2\bb.txt")) { } using (StreamWriter sw = File.AppendText(@"D:\360Downloads\dir2\bb.txt")) { }
使用File 类型的这些新方法,只用几行代码就可以批量读写数据。更好的是,每一个成员都自动关闭基层文件句柄
File新方法如下
方法 | 作用 |
ReadAllBytes() | 打开指定文件,以字节数组形式返回二进制数据,然后关闭文件 |
ReadAllLines() | 打开指定文件,以字符串教组形式返回字符教据.然后关闭文件 |
ReadAllText() | 打开指定文件.以System.String形式返回字符数据.然后关闭文件 |
WriteAllBytes() | 打开指定文件.写人字节数组.然后关闭文件 |
WriteAllLines() | 打开指定文件.写人字符串教组,然后关闭文件 |
WriteAllText() | 打开指定文件.写人字符数据.然后关闭文件 |
举例如下
Console.WriteLine("批量读写数据"); string[] myTasks = { "蒸甜糕", "做糖饼", "腌桂花蜜", "做桂花酿" }; //写入文件 File.WriteAllLines(@"D:\360Downloads\dir2\bb.txt", myTasks); //重新读取然后输出 foreach (string item in File.ReadAllLines(@"D:\360Downloads\dir2\bb.txt")) { Console.WriteLine(item); }
Stream抽象类
在 I/ O 操作中,流代表了在源文件和目标文件之间传输的一定量的数据。无论使用什么设备(文件、网络连接和打印机等)存储或者显示字节。”流”都能提供一种通用的方式来和字节队列进行交互
“流”的概念不仅仅局限于文件输入/输出. NET类库提供了”流”来访问网络、内存地址和其他一些与流相关的抽象设备
Stream派生类型把数据表现为原始的字节流。因此,使用原始的Stream类型有点模糊。一些从Stream派生的类型支持寻址(指获取和调整当前在流中位置的过程)。
下面有关 抽象Stream成员
抽象Stream成员 | |
成员 | 作用 |
CanRead,CanWrite和CanSeek | 检侧当前流是否支持读、寻址和写 |
Close() | 关闭当前流并释放与之关联的所有资源(如套接字和文件句柄)。在内部,这个方法是Dispose()方法的别名.因此"关闭流"从功能上说等价于"释放流" |
Flush() | 使用当前的缓冲状态更新基层的数据源或储存库。如果流不实现缓冲.这个方法什么都不做 |
Length | 返回流的长度,以字节来表示 |
Position | 检侧在当前流中的位置 |
Read()和ReadByte() | 从当前流读取字节序列或一个字节。井将此流中的位置偏移读取的字节数 |
Seek | 设置当前流中的位置 |
SeekLength() | 设置当前流的长度 |
Write()和WriteByte() | 向当前流中写人字节序列或一个字节,将此流中的当前位置偏移写人的字节数 |
使用FileStream
Fi1eStream类以合适的方式为基于文件的流提供了抽象Stream成员的实现。这是一个相当原始的流,它只能读取或写人一个字节或者字节数组。其实,我们通常不需要直接和 FileStream类型的成员交互,而是使用各种Stream包装类,它们能更方便地处理文本数据和.NET 类型。
具体使用如下
Console.WriteLine("***FileStream***"); //获取一个FileStream对象 using (FileStream fs = File.Open(@"D:\360Downloads\dir2\cc.txt", FileMode.OpenOrCreate)) { string msg = "Hello"; //把字符串编码成字节数组 byte[] msgAsByteArray = Encoding.Default.GetBytes(msg); //写入文件 fs.Write(msgAsByteArray, 0, msgAsByteArray.Length); //重置流的内部位置 fs.Position = 0; //从文件读取字节并显示在控制台 Console.WriteLine("**Your Message**"); byte[] bytesFromFile = new byte[msgAsByteArray.Length]; for (int i = 0; i < msgAsByteArray.Length; i++) { bytesFromFile[i] = (byte)fs.ReadByte(); Console.WriteLine(bytesFromFile[i]); } //解码后字符串 Console.WriteLine("Decoded Messges:"); Console.WriteLine(Encoding.Default.GetString(bytesFromFile)); }
而FileStream的缺点:需要操作原始字节
使用streamwriter和streamreader类型
当需要读写基于字符的数据(比如字符串)的时候. streamWriter 和 streamReader 类就非常有用了。它们都默认使用Unicode字符.当然我们也可以提供一个正确配置的System.Text.Encoding 对象引用用来改变默认配置。
StreaoReader 和相关的 StringReader类型都从 TextReader 抽象类派生
StreaoWriter 和相关的 StringWriter类型都从 TextWriter 抽象类派生
写入文本文件(TextWriter )
下面是关于 TextWriter核心成员
TextWriter核心成员 | |
成员 | 作用 |
Close() | 关闭当前编写器并释放任何与该编写器关联的系统资源。在这个过程中.缓冲区将被自动清理(这个成员在功能上等同与调用Dispose()方法) |
Flush() | 清理当的编写器的所有缓冲试.使所有缓冲数据写人基础设备.但是不关闭偏写器 |
NewLine | 代表派生的编写器类的行结束符字符串。默认行结束符字符串是回车符后接一个换行符(\r\n) |
Write() | 这个重载的方法将一行写入文本流.不限行结束符 |
WriteLine() | 这个重载的方法将一行写入文本流,后跟行结束符 |
派生的StreamWriter类提供了对Write(), close ()和Flush()方法的有效实现.而且还定义了
AutoFlush 属性。如果把这个属性设置为 true 的话, StreamWriter 会在每次执行一个写操作后,立即写入数据并清理缓冲区。设置 AutoFlush为 false 能获得更好的性能,这样的话.使用 StreamWriter完成写操作后需要调用 Close()。
写入文本文件代码如下:
Console.WriteLine("****Fun with StreamWriter*****"); using (StreamWriter writer = File.CreateText(@"D:\360Downloads\dir2\re.txt")) { writer.WriteLine("鱼是做给大家伙儿吃的,乔初熏发觉这些人都挺爱吃甜口吃食,便打算做个糖醋鲤"); writer.WriteLine("鱼是做给大家伙儿吃的,乔初熏发觉这些人都挺爱吃甜口吃食,便打算做个糖醋鲤"); writer.WriteLine("鱼是做给大家伙儿吃的,乔初熏发觉这些人都挺爱吃甜口吃食,便打算做个糖醋鲤"); for (int i = 0; i < 10; i++) { writer.Write(i + " "); } } Console.WriteLine("Created file");
读文本文件(TextReader )
下面是关于 TextReader 核心成员
TextReader 主要成员 | |
Peek() | 返回下一个可用字符,而不更改读取器位置。返回-l表示已经到了流的尾部 |
Read() | 从输人流中读取救据 |
ReadBlock() | 从当前流中读取最大计数字符,并从索引开始将该数据写人缓冲区 |
ReadLine() | 从当前流中读取一行字符,并将数据作为字符串返回(返回空字符串代表EOF) |
ReadToEnd | 读取从当前位置到流结尾的所有字符,并将它们作为一个字符串返回 |
读文本文件代码如下:
Console.WriteLine("***Fun with StreamReader***"); using (StreamReader sr = File.OpenText(@"D:\360Downloads\dir2\re.txt")) { string inpt = null; while ((inpt=sr.ReadLine())!=null) { Console.WriteLine(inpt); } }
直接创建streamwriter/streamreader类型
Console.WriteLine("直接创建streamwriter/streamreader类型"); using (StreamWriter sw = File.CreateText(@"D:\360Downloads\dir2\chuchu.txt")) { string mag = " 不一会儿,大锅里的水烧的滚沸,乔初熏把手洗干净,伸手捏了些羊肉,攒成丸子便往锅里一丢,小桃儿在旁边看着直咋舌:“初熏姐姐,这样会不会太松了。”她见乔初熏手上也不怎么使劲儿,生怕羊肉丸子一进锅便散了。"; sw.WriteLine(mag); Console.WriteLine("ok"); } using (StreamReader sr = File.OpenText(@"D:\360Downloads\dir2\chuchu.txt")) { string input = null; while ((input = sr.ReadLine()) != null) { Console.WriteLine(input); } }
使用stringwriter和stringreader类型
使用 StringWriter 和 stringReader 类型,我们可以将文本信息当做内存中的字符一样来处理。当想为基层缓冲区添加基于字符的信息的时候,它们就非常有用。
Console.WriteLine("Fun StringWriter"); using (StringWriter sw = new StringWriter()) { sw.WriteLine("乔初熏手上动作不停,一边笑着解释道:“不会。手劲儿太大了反而不好。汆出来的丸子容易发死,吃起来不够鲜嫩."); Console.WriteLine(sw); }
因为StringWriter 和 StreamWriter 都从一个基类(TextWriter )派生.它们的写操作逻辑代码或多或少有点相同。但需要知道, StringWriter 还有一个特点.那就是它能通过 GetStringBuilder() 方法来
获取一个System.Text.StringBuilder 对象:
Console.WriteLine("GetStringBuilder"); using (StringWriter sw = new StringWriter()) { sw.WriteLine("很快,一边蒸锅里的鱼也差不多到火候了。乔初熏拿着勺子搅了搅汤,让小桃儿把鱼端出来。"); Console.WriteLine(sw); StringBuilder sb = sw.GetStringBuilder(); sb.Insert(0, "Hey"); Console.WriteLine(sb.ToString()); sb.Remove(0, "Hey".Length); Console.WriteLine(sb.ToString()); }
使用binarywriter和binaryreader
BinaryWriter和binaryreader都从 System.Object 直接派生。这些类可以让我们从基层流中以简洁的二进制格式读取或写人离散数据类型。 BinaryWriter 类型定义了一个多次重载的Write方法,用于把数据类创写入基层的流,除Write()方法, BinaryWriter还提供了另外一些成员让我们能获取或设置从Stream派生的类型,并且提供了随机数据访问
下面有关 BinaryWriter核心成员
BinaryWriter核心成员 | |
BaseStream | 这个只读属性提供了BinaryWriter对象使用的基层流的访问 |
Close() | 这个方法关闭二进制流 |
Flush() | 这个方法别新二进制流 |
seek() | 这个方法设置当前流的位置 |
Write | 这个方法将值写入当前流 |
下面有关 BinaryReaer核心成员
BinaryReader成员 | |
BaseStream | 这个只读属性提供了BinaryReder对象使用的基层流的访问 |
Close() | 这个方法关闭二进制阅读器 |
PeekChar() | 这个方法返回下一个可用的字符,并且不改变指向当前字节或字符的指针位置 |
Read() | 读取给定的字节或字符,并把它们存入数组 |
Readxxx() | BinaryReader类定义了许多 Read()方法来从流中获取下一个类型(ReadBoolean() ReadByte() ReadInt32()) |
下面是有关的代码
Console.WriteLine("*****Fun with Writer 和Reader******"); FileInfo f = new FileInfo(@"D:\360Downloads\dir2\aa.txt"); using (BinaryWriter bw = new BinaryWriter(f.OpenWrite())) { Console.WriteLine(bw.BaseStream); double a = 1234.67; int i = 3452; string str = "Hello"; bw.Write(a); bw.Write(i); bw.Write(str); } Console.WriteLine("Done!"); using (BinaryReader br = new BinaryReader(f.OpenRead())) { Console.WriteLine(br.ReadDouble()); Console.WriteLine(br.ReadInt32()); Console.WriteLine(br.ReadString()); }
以编程方式"观察"文件 FileSystemWatcher
Console.WriteLine("****FileSystemWatcher****"); FileSystemWatcher watcher = new FileSystemWatcher(); try { watcher.Path = @"D:\360Downloads\dir2"; } catch (Exception e) { Console.WriteLine(e.Message); } watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = "*.txt"; watcher.Changed += new FileSystemEventHandler(OnChanged); watcher.Created += new FileSystemEventHandler(OnChanged); watcher.Deleted += new FileSystemEventHandler(OnChanged); watcher.Renamed += new RenamedEventHandler(OnRenamed); watcher.EnableRaisingEvents = true; Console.WriteLine("Press q"); while (Console.ReadLine() != "q") static void OnChanged(object source, FileSystemEventArgs e) { Console.WriteLine("File:{0}{1}", e.FullPath, e.ChangeType); } static void OnRenamed(object source, FileSystemEventArgs e) { Console.WriteLine("File:{0},OnRenamed:{1}", e.FullPath, e.ChangeType); }