关于文件系统操作的几个常用类和使用
流结构和文件的二进制和字符读写
文件监控类FileSystemWatcher的使用
首先先看一张C#常用与文件操作有关的类图
所有的这些类都在System.IO的命名空间中,所以一下的所有代码,使用时都要先添加
using System.IO; .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }另外在这部分程序中出现异常均为IOException
开始介绍一下文件和目录的操作。
文件使用FileInfo类或File类。区别是FileInfo有生成一个实例,而File类只是一个静态类。如果对文件只需要进行一次性操作,使用File类会更好。下面代码展示FileInfo类的使用,File类使用类似。更多的方法可以直接转到FileInfo的类定义中查看。
1: static void Main(string[] args) 2: { 3: FileInfo test; 4: try 5: { 6: test = new FileInfo(@"D:/test.txt"); 7: if (!test.Exists)//文件是否存在 8: { 9: test.Create();//创建文件 10: } 11: //第二个参数表示是否允许覆盖现有文件。 12: //test.CopyTo(@"E:/test.txt",false); 13: Console.WriteLine("目录名: {0}", test.DirectoryName); 14: Console.WriteLine("文件名: {0}", test.Name); 15: Console.WriteLine("文件大小为{0}字节", test.Length); 16: //test.Delete();删除文件 17: //test.MoveTo(@"D:/1.txt");移动/重命名 18: } 19: catch (IOException e) 20: { 21: Console.WriteLine(e.Message); 22: } 23: Console.ReadKey(); 24: }.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }对于目录的操作也是类似的分为了DirectoryInfo和Directory两个类。
所能实现的方法可以直接参考定义,都不难理解。但是定义中没有提供整个目录的复制功能。需要自己递归实现,具体看以下代码
1: static void CopyDirectory(DirectoryInfo source, DirectoryInfo destination) 2: { 3: try 4: { 5: if (!destination.Exists) 6: { 7: destination.Create(); 8: } 9: 10: FileInfo[] files = source.GetFiles(); 11: foreach (FileInfo file in files) 12: { 13: file.CopyTo(destination.FullName + file.Name); 14: } 15: 16: DirectoryInfo[] directorys = source.GetDirectories(); 17: foreach (DirectoryInfo directory in directorys) 18: { 19: //构建目标子目录的绝对地址,目标目录地址+文件夹名 20: string newDirName = Path.Combine(destination.FullName,directory.Name); 21: //复制子目录 22: CopyDirectory(directory, new DirectoryInfo(newDirName)); 23: } 24: } 25: catch (IOException e) 26: { 27: Console.WriteLine(e.Message); 28: } 29: 30: } 31: static void Main(string[] args) 32: { 33: try 34: { 35: DirectoryInfo test = new DirectoryInfo(@"D:/test"); 36: if (!test.Exists) 37: { 38: test.Create(); 39: } 40: CopyDirectory(test, new DirectoryInfo(@"E:/test")); 41: 42: } 43: catch (IOException e) 44: { 45: Console.WriteLine(e.Message); 46: } 47: Console.ReadKey(); 48: } 49:
.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }以上介绍的都是文件和目录级别的操作下面介绍文件的读写。
文件的读写分为两种模式,一种是按二进制方式读写,另一种按文本方式读写。分别用于一般二进制文件和文本文件。
在给代码前有两个知识点需要提一下。
一个是我们的硬盘磁盘都是以线性方式保存数据,所以我们就可以构建一个流结构来对文件进行读写。通过流结构,让数据流向文件,或者是让文件内容流向变量。
另一个是文件指针。就是一个指向我们将要操作的位置。比如我们文件指针位于文件的第10个字节,我们的读写操作都是从文件指针的位置即第10个字节开始。相当于我们编辑文件时能看到的光标。可以用Seek()方法进行操作。
首先我们先看如何读写二进制文件,使用FileStream类。下面代码实现向image.ima写入boot.bin。注意这里是写入,不是插入,假设我们boot.bin的文件大小为N个字节,那么读写完后image.imz原来开头的N个字节的内容就被修改掉了,而第N+1及之后的内容不变。
1: static void Main(string[] args) 2: { 3: FileStream source = null; 4: FileStream destination = null; 5: try 6: { 7: source = new FileStream(@"D:/boot.bin", FileMode.Open, FileAccess.Read); 8: destination = new FileStream(@"D:/image.imz", FileMode.Open, FileAccess.Write); 9: byte[] buffer = new byte[215]; 10: int count = 0; 11: count = source.Read(buffer, 0, 215); 12: while (count != 0) 13: { 14: destination.Write(buffer, 0, count); 15: count = source.Read(buffer, 0, 215); 16: } 17: Console.WriteLine("OK"); 18: } 19: catch (IOException e) 20: { 21: Console.WriteLine(e.Message); 22: } 23: finally 24: { 25: if (source != null) 26: { 27: source.Close(); 28: } 29: if (destination != null) 30: { 31: destination.Close(); 32: } 33: } 34: Console.ReadKey(); 35: } 创建FileSream的时候后面两个参数是枚举类型,设置了文件的模式和权限。 如果要对文本文件进行读写需要用到StreamWriter和StreamReader类。初始化他们的时候最好使用FileStream作为参数,不然那两个类无法设置文件的访问权限,默认都是可以读写的。 具体的使用方法参考下面代码 1: static void Main(string[] args) 2: { 3: FileStream file = null; 4: StreamWriter sw = null; 5: StreamReader sr = null; 6: string[][] table = new string[3][]; 7: table[0] = new string[3] { "11", "22", "33" }; 8: table[1] = new string[3] { "44", "55", "66" }; 9: table[2] = new string[3] { "77", "88", "99" }; 10: try 11: { 12: file = new FileStream(@"D:/test.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite); 13: 14: sw = new StreamWriter(file); 15: foreach (string[] i in table) 16: { 17: foreach (string str in i) 18: { 19: Console.Write("{0} ",str); 20: sw.Write("{0} ",str); 21: } 22: Console.WriteLine(); 23: sw.WriteLine(); 24: } 25: sw.Flush();//把缓存区内容输出 26: Console.WriteLine("write"); 27: 28: file.Seek(0, SeekOrigin.Begin);//把文件指针移到文件头 29: sr = new StreamReader(file); 30: string strline = sr.ReadLine(); 31: while (strline != null) 32: { 33: string[] strElement = strline.Split(' '); 34: foreach (string element in strElement) 35: { 36: Console.Write("{0} ", element); 37: } 38: Console.WriteLine(); 39: 40: strline = sr.ReadLine(); 41: } 42: Console.WriteLine("read"); 43: } 44: catch (IOException e) 45: { 46: Console.WriteLine(e.Message); 47: } 48: finally 49: { 50: if (sw != null) 51: { 52: sw.Close(); 53: } 54: if (sr != null) 55: { 56: sr.Close(); 57: } 58: if (file != null) 59: { 60: file.Close(); 61: } 62: } 63: Console.ReadKey(); 64: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
最后介绍一个文件监控实例,利用FileSystemWatcher可以监控文件的修改,删除,创建,重命名等事件。只要添加相应的事件处理函数,就可以在方式相应事件时执行函数。
下面的代码监控了文件的删除事件,其他的事件可以仿照删除时间处理函数进行处理
1: static void Main(string[] args) 2: { 3: FileSystemWatcher watcher = new FileSystemWatcher(@"D:/","1.txt"); 4: watcher.Deleted += OnDelete; 5: watcher.EnableRaisingEvents = true; 6: 7: Console.ReadKey(); 8: 9: } 10: static void OnDelete(object sender, FileSystemEventArgs e) 11: { 12: Console.WriteLine("{0} had been deleted!", e.FullPath); 13: }.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
关于文件处理的类,还有很多方法和属性没办法讲解,都可以参考类的定义来使用。