22.1 概述
文件是任何应用程序开发时必不可少的操作,.Net框架下提供的文件操作基本都位于System.IO命名空间下。
22.2 File和FileInfo
这两个类用来操作硬盘上的文件,File类主要通过静态方法实现,而FileInfo类则是通过实例方法实现的。
FileInfo类的实例成员提供了与FIle类差不多的功能,大多数情况下,他们可以相互互换使用,但是由于FIle类提供的方法都是静态方法,使用频率居多。
eg:
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;namespace MSN{ class MainClass { public static void WriteFile() { FileStream fs = null; StreamWriter writer = null; //默认存放于工程bin/Debug目录下 string path = "test.txt"; if (!File.Exists(path)) { fs = File.Create(path); Console.WriteLine("新建一个文件:{0}", path); } else { fs = File.Open(path, FileMode.Open); Console.WriteLine("文件已经存在,直接打开"); } writer = new StreamWriter(fs); writer.WriteLine("测试文本"); writer.Flush(); writer.Close(); fs.Close(); }• public static void Main(string[] args) { WriteFile(); } }}
以上代码通过File.Exists方法判断指定路径下的文件是不是存在,如果文件存在,则直接调用File.Open将文件打开,否则将调用Create方法创建一个文件。然后,代码会初始化一个StreamWriter对象,然后向文本中写入字符串操作。最后,程序会通过调用Flush方法清空缓冲区,然后将所有的缓冲区数据写入文件,并且调用CLose方法关闭数据流。
22.3 Directory和DirectoryInfo
这两个类都包含了一组用来创建,移动,删除和枚举所有目录或者子目录的成员,如下表所示:
DirectoryInfo功能与这个类似,大多数情况下两者可以互换使用。
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;namespace MSN{ class MainClass { public static void DirectoryOperate() { string dirPath = Directory.GetCurrentDirectory(); Console.WriteLine(dirPath); string filePath = string.Format("{0}/{1}", dirPath, "hello.txt"); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); Console.WriteLine("创建一个目录"); } else { Console.WriteLine("存在目录"); } FileInfo file = new FileInfo(filePath); if (!file.Exists) { file.Create(); Console.WriteLine("创建一个文件"); } else { Console.WriteLine("存在"); } } public static void Main(string[] args) { DirectoryOperate(); } }}
【遍历指定目录下所有的文件】
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;namespace MSN{ class MainClass { public static void ForeachDirectory() { string[] files = Directory.GetFiles("/Users/ww/Desktop/tt/tt/bin/Debug", "*", SearchOption.AllDirectories); Console.WriteLine(files.Length); for (int i = 0, len = files.Length; i < len; i++) { string filePath = files[i]; Console.WriteLine(filePath); } } public static void Main(string[] args) { ForeachDirectory(); } }}
22.4 文件流
22.4.1 Stream
流可以理解为内存中的字节序列,Stream是所有流的抽象基类,每个具体的存储实体都可以通过Stream派生类来实现。如FileStream就是这种存储实体。同样,流也涉及三个基本操作。
- 对流进行读取:将流中的数据读取到具体的数据结构中
- 对流进行写入:把数据结构中的数据写入到流中
- 对流进行查找:对流内的当前位置进行查询和修改
Stream类的一些常用成员如下表所示:
其中Stream有几个常见的派生类, NetworkStream,FileStream,MemoryStream,GZipStream.
- NetworkStream提供网络通信的基础数据流
- FileStream用于将数据以流的形式写入文件,或者从文件中读取
- MemoryStream用于对内存中的数据进行写入或者读取
- GZipStream提供用于压缩和解压缩的数据流
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;using System.Text;namespace MSN{ class MainClass { public static void StreamOperation() { string filePath = "test.txt"; using (FileStream fileStream = File.Open(filePath, FileMode.OpenOrCreate)) { string msg = "HelloWorld"; byte[] msgByteArray = Encoding.Default.GetBytes(msg); Console.WriteLine("开始写入文件"); fileStream.Write(msgByteArray, 0, msgByteArray.Length); fileStream.Seek(0, SeekOrigin.Begin); Console.WriteLine("写入文件的数据为"); byte[] bytesFromFile = new byte[msgByteArray.Length]; fileStream.Read(bytesFromFile, 0, msgByteArray.Length); Console.WriteLine(Encoding.Default.GetString(bytesFromFile)); } } public static void Main(string[] args) { StreamOperation(); } }}
以上代码首先调用File.Open方法来创建一个FileStream实例对象,然后调用Write方法把字符串的字节数组写入到流中,接着调用Seek方法重置流内部的位置,最后调用Read方法将数据从流中读取到字节数组,并把写入的信息输出到控制台。
System.IO命名空间提供了不同的读写器,以对流中的数据进行操作。这些类通常是成对出现的:一个从流中读取数据,另外一个写入数据。
22.4.2 FileStream
System.IO 命名空间中的 FileStream 类有助于文件的读写与关闭。该类派生自抽象类 Stream。
通过创建一个 FileStream 对象来创建一个新的文件,或打开一个已有的文件。创建 FileStream 对象的语法如下:
public FileStream (string path, FileMode mode, FileAccess access, FileShare share);public FileStream (string path, FileMode mode, FileAccess access);public FileStream (string path, FileMode mode);……
例如,创建一个 FileStream 对象 FS 来读取名为 sample.txt 的文件:
FileStream FS = new FileStream("sample.txt", FileMode.Open, FileAccess.Read, FileShare.Read);
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;using System.Text;namespace MSN{ class MainClass { public static void Main(string[] args) { FileStream F = new FileStream("test.dat", FileMode.OpenOrCreate, FileAccess.ReadWrite); for (int i = 1; i <= 20; i++) { F.WriteByte((byte)i); } F.Position = 0; for (int i = 0; i <= 20; i++) { Console.Write(F.ReadByte() + " "); } F.Close(); } }}
22.4.3 StreamReader/StreamWriter
StreamReader 和 StreamWriter 类用于文本文件的数据读写。这些类从抽象基类 Stream 继承,Stream 支持文件流的字节读写。
【StreamReader】
StreamReader 类继承自抽象基类 TextReader,表示阅读器读取一系列字符。
下表列出了 StreamReader 类中一些常用的方法:
eg:
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;using System.Text;namespace MSN{ class MainClass { public static void Main(string[] args) { try { // 创建一个 StreamReader 的实例来读取文件 // using 语句也能关闭 StreamReader using (StreamReader sr = new StreamReader("/Users/ww/Desktop/Jamaica.txt")) { string line; // 从文件读取并显示行,直到文件的末尾 while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); } } } catch (Exception e) { // 向用户显示出错消息 Console.WriteLine("The file could not be read:"); Console.WriteLine(e.Message); } } }}
【StreamWriter】
StreamWriter 类继承自抽象类 TextWriter,表示编写器写入一系列字符。
下表列出了 StreamWriter 类中一些常用的方法:
eg:
// #region << 版 本 注 释 >>// /*----------------------------------------------------------------// // Copyright (C) 2019 极客部落// // 版权所有。 // // 文件名:Program.cs// // 文件功能描述:// // // // 创建者:GeekTribe// // 时间:14:05// //----------------------------------------------------------------*/// #endregionusing System;using System.IO;using System.Text;namespace MSN{ class MainClass { public static void Main(string[] args) { string[] names = { "Zara Ali", "Nuha Ali" }; using (StreamWriter sw = new StreamWriter("names.txt")) { foreach (string s in names) { sw.WriteLine(s); } } // 从文件中读取并显示每行 string line = ""; using (StreamReader sr = new StreamReader("names.txt")) { while ((line = sr.ReadLine()) != null) { Console.WriteLine(line); } } } }}
22.5 文件异步操作
在同步操作中,如果向文件中写入大量数据,方法将一直处于等待状态,直到写入完成。若是使用异步操作,方法就可以在写入操作的同时继续执行后面的操作。下面以FileStream为例子,介绍对文件进行异步操作的方法。
FileStream共有15个构造函数,其中只有一个构造函数可以指定异步操作,该构造函数的定义如下:
FileStream(string path,FileMode mode,FileAccess access,FileShare share,int bufferSize,bool useAsync)
最后一个参数useAsync用于指定程序使用的是异步还是同步,如果设置为true,异步方式来设置FileStream。