用于输入和输出的类
来自 System.IO
用于访问文件系统的类
类 | 说明 |
File | 静态实用类,用于移动、复制和删除文件 |
Directory | 静态实用类,用于移动、复制和删除目录 |
Path | 实用类,用于处理路径名称 |
FileInfo | 表示磁盘上的物理文件,该类包含处理此文件的方法,要完成对文件的读写操作,必须创建 Stream 对象 |
DirectoryInfo | 表示磁盘上的物理目录,该类包含处理此目录的方法 |
FileSystemInfo | FileInfo 与 Directory 的基类,可以使用多态性同时处理文件和目录 |
FileSystemWatcher | 用于监控文件和目录,提供了这些文件和目录发生变化时应用程序可以捕获的事件 |
System.IO.Compression
- DeflateStream,写入时自动压缩数据/读取时自动解压,使用 Deflate 算法
- GZipStream,写入时自动压缩数据/读取时自动解压,使得 GZIP 算法
File 类和 Directory 类
File 类的静态方法
方法 | 说明 |
Copy() | 将文件从源位置复制到目标位置 |
Create() | 在指定的路径上创建文件 |
Delete() | 删除文件 |
Open() | 返回指定路径上的 FileStream 对象 |
Move() | 将指定的文件移到到新位置,可在新位置为文件指定不同的名称 |
Directory 类的静态方法
CreateDirectory() | 创建具有指定路径的目录 Delete() | 删除指定的目录及其中的所有文件 GetDirectories() | 返回表示指定目录下的目录名的 string 对象数组 EnumerateDirectories() | 返回指定目录名下 IEnumerable<string> 目录集合 GetFiles() | 返回在指定目录中的文件名的 string 对象数组 EnumerateFiles() | 返回文件名的 IEnumerable<string> 集合 GetFileSystemEntries() | 返回指定目录中的文件和目录名的 string 对象数组 EnumerateFileSystemEntries() | 返回文件和目录名的 IEnumerable<string> 集合 Move() | 将指定目录移到新位置,可在新位置为文件夹指定一个新名称
- 在处理大量文件与目录时,EnumerateXXX 比 GEtXXX 性能好
FileInfo 类
FileInfo aFile = new FileInfo(@"C:\Log.txt"); // @字符表示引号中的\不转义if (aFile.Exists) WriteLine("File Exists");if (File.Exists("Data.txt")) WriteLine("File Exists");
FileSystem 的属性
属性 | 说明 |
Attributes | 使用 FileAttributes 枚举,获取或者设置当前文件或目录的特性 |
CreationTime, CreationTimeUtc | 获取当前文件的创建日期和时间,可使用 UTC 和非 UTC 版本 |
Extension | 提取文件的扩展名,只读属性 |
Exists | 确认文件是否存在,只读抽象属性,在 FileInfo 和 DirectoryInfo 中进行了重写 |
FullName | 检索文件的完整路径,只读属性 |
LastAccessTime, LastAccessTimeUtc | 获取或设置上次访问当前文件的日期和时间,可使用 UTC 和非 UTC 版本 |
LastWriteTime, LastWriteTimeUtc | 获取或设置上次写入当前文件的日期和时间,可使用 UTC 和非 UTC 版本 |
Name | 检索文件的完整路径,只读抽象属性,,在 FileInfo 和 DirectoryInfo 中进行了重写 |
FileInfo 专有属性
属性 | 说明 |
Directory | 表示包含当前文件的目录,只读属性,返回 DirectoryInfo 对象 |
DirectoryName | 返回文件目录的路径,只读属性 |
IsReadOnly | 文件只读特性的快捷方式,也可通过 Attributes 来访问 |
Length | 获取文件的大小(以字节为单位),返回 long 值,只读属性 |
DirectoryInfo 类
批量处理时使用此类,实例化后可使用
DirectoryInfo 专有属性
属性 | 说明 |
Parent | 检索一个 DirctoryInfo 对象,表示包含当前目录的目录,只读属性 |
Root | 检索一个 DirctoryInfo 对象,表示包含当前目录的根目录,只读属性 |
路径名和相对路径
- 工作目录起初设置为运行应用程序的目录
- 使用 Directory.GetCurrentDirectory() 找出工作目录的当前设置
- 使用 Directory.SetCurrentDirectory() 设置新的工作目录
流
- 在 .NET Framework 中进行的所有输入和输出工作都要用到注(Steam)
- 流是序列化设备(serial device)的抽象表示
- 流可以表示几乎所有源,如键盘、物理磁盘文件、网络位置、打印机等等
使用流的类
包含在 System.IO 空间
流类
类 | 说明 |
FileStream | 可以同步或异步地读写此文件 |
StreamReader | 从流中读取字符数据,可以使用 FileStream 作为基类创建 |
streamWriter | 向流写入字符数据,可以使用 FileStream 作为基类创建 |
FileStream 对象
- FileStream 类操作的是字节和字节数组,Steam 类操作的是字符数据
// 常用版本1FileStream aFile = new FileStream(filename, FileMode. );// 常用版本2FileStream aFile = new FileStream(filename, FileMode. , FileAccess. );
FileAccess 枚举成员
成员 | 说明 |
Read | 打开文件,用于只读 |
Write | 打开文件,用于写入 |
ReadWrite | 打开文件,用于读写 |
FileMode 枚举成员
成员 | 文件存在 | 文件不存在 |
Append | 打开文件,指向文件的末尾处,只能与 FileAccess.Write 结合使用 | 创建一个新文件,只能与 FileAccess.Write |
Create | 删除该文件,然后创建新文件 | 创建新文件 |
CreateNew | 如果文件存在,抛出异常 | 创建新文件 |
Open | 打开文件,流指向文件开头处 | 抛出异常 |
OpenOrCreate | 打开文件,流指向文件开头处 | 创建新文件 |
Truncate | 打开文件,清除其内容,流指向文件开头处,保留文件的初始创建时间,抛出异常 | |
// 基于 File FileStream aFile = File.OpenRead("Data.txt");// 基于 FileInfoFileInfo aFileInfo = new FileInfo("Data.txt");FileStream aFile = aFileInfo.OpenRead();
文件位置
- 大多数情况下,文件打开时,文件指都指向文件开头处,但可以修改此指针位置
- 文件读写时文件指针会随之改变
SeekOrign 枚举成员
成员 | 说明 |
Begin | 开始位置,文件的第1个字节 |
Current | 当前位置 |
End | 结束位置 |
aFile.Seed(移动距离(以字节为单位,可以为负值), SeekOrign. <开始计算的起始位置> );// 举例aFile.Seek(8, SeekOrign.Begin); // 从文件开始位置,移动 8 个字节aFile.Seek(2, SeekOrign.Current); // 从当前位置,移动 2 个字节aFile.Seek(-5, SeekOrign.End); // 从文件结束位置,向前移动5个字节 开始计算的起始位置>
读取文件
FileStream.Read(传入的字节数组(用于接收 FileStream 对象中的数据), 字节数组中开始写入数据的位置(通常是0), 从文件中读取的字节数);
byte[] byteData = new byte[200];char[] charData = new char[200];try{ FileStream aFile = new FileStream("../../Program.cs", FileMode.Open); aFile.Seek(174, SeekOrigin.Begin); aFile.Read(byteData, 0, 200); // 读取}catch(IOException e){ WriteLine("An IO Exception has been thrown!"); WriteLine(e.ToString()); ReadKey(); return;}Decoder d = Encoding.UTF8.GetDecoder(); // 注意d.GetChars(byteData, 0, byteData.Length, charData, 0); // 字节数组转字符数组WriteLine(charData);ReadKey();
写入数据
byte[] byteData;char[] charData;try{ FileStream aFile = new FileStream("Temp.txt", FileMode.Create); charData = "My pink half of the drainpip.".ToCharArray(); // 字符串 转换成 字符数组 byteData = new byte[charData.Length]; Encoder e = Encoding.UTF8.GetEncoder(); // 注意 e.GetBytes(charData, 0, charData.Length, byteData, 0, true); // 字符数组转字节数组,true:清空内存,释放对象 aFile.Seek(0, SeekOrigin.Begin); aFile.Write(byteData, 0, byteData.Length);}catch (IOException ex){ WriteLine("An IO exception has been thrown!"); WriteLine(ex.ToString()); ReadKey(); return;}
SteamWrite 对象
// 通过 FileStream 创建FileStream aFile = new FileStream("log.txt", FileMode.CreateNew);StreamWriter sw = new StreamWriter(aFile);// 直接创建StreamWriter sw = new SteamWriter("Log.txt", true); // true,表示追回文件内容
try{ FileStream aFile = new FileStream("Log.txt", FileMode.OpenOrCreate); StreamWriter sw = new StreamWriter(aFile); bool truth = true; sw.WriteLine("Hello to you."); sw.Write($"It is now {DateTime.Now.ToLongDateString()}"); sw.Write("and things are looking good."); sw.Write("More than that,"); sw.Write($" it`s {truth} that C# is fun."); sw.Close();}catch (IOException e){ WriteLine("An IO exception has been thrown!"); WriteLine(e.ToString()); ReadLine(); return;}
SteamReader 对象
// 通过 FileStream 创建FileStream fileStream = new FileStream("log.txt", FileMode.Open);StreamReader sr = new StreamReader(fileStream);// 直接创建StreamReader sr = new StreamReader("log.txt");
读取文件的方法
方法 | 说明 |
Peek() | 读取文件中下一个字符的值,但不移动指针位置 |
Read() | 读取下一个字符,同时移动指针位置 |
Read(char[] buffer, int index, int count) | 从 index 开始,读取 count 个字符放入 buffer |
ReadLine() | 读取一行文本 |
ReadToEnd() | 获取文件中的所有文本 |
// 按行读取文件内容string line;try{ FileStream fileStream = new FileStream("log.txt", FileMode.Open); StreamReader sr = new StreamReader(fileStream); line = sr.ReadLine(); while (line != null) { WriteLine(line); line = sr.ReadLine(); } sr.Close();}catch (IOException err){ WriteLine(err.Message); return;}// 按字符读取文件内容int charCode;try{ FileStream fileStream = new FileStream("log.txt", FileMode.Open); StreamReader sr = new StreamReader(fileStream); charCode = sr.Read(); // 读取的是一个正整数 while (charCode != -1) { WriteLine(Convert.ToChar(charCode)); // 需要通过 Convert.ToChar 转换为字符 charCode = sr.Read(); } sr.Close();}catch (IOException err){ WriteLine(err.Message); return;}// 将整个文件作为一个字符串返回,文件内容会放在内存中,注意string content;content = sr.ReadToEnd();WriteLine(content);sr.Close();// 通过 File.ReadLines() 读取,返回值为 IEnumerable 集合foreach (string line in File.ReadLines("Log.txt")) WriteLine(line);
异步文件访问
- 适用于 FileStream, StreamReader, StreamWrite 类
- 带有 Async 后缀的方法,如 ReadLineAsync()
读写压缩文件
- 引入 System.IO.Compression 名称空间
- GZIP 与 Deflate 算法
- 对应 DeflateStream 与 GZipStream 类
static void SaveCompressedFile(string filename, string data){ FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write); GZipStream compressStream = new GZipStream(fileStream, CompressionMode.Compress); // 关键 StreamWriter writer = new StreamWriter(compressStream); writer.Write(data); writer.Close();}static string LoadCompressedFile(string filename){ FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); GZipStream compressStream = new GZipStream(fileStream, CompressionMode.Decompress); // 关键 StreamReader reader = new StreamReader(compressStream); string data = reader.ReadToEnd(); reader.Close(); return data;}static void Main(string[] args){ try { string filename = "compressedFile.txt"; WriteLine("Enter a string to compress (will be repeated 100 times):"); string sourceString = ReadLine(); StringBuilder sourceStringMultiplier = new StringBuilder(sourceString.Length * 100); for (int i = 0; i < 100; i++) sourceStringMultiplier.Append(sourceString); sourceString = sourceStringMultiplier.ToString(); WriteLine($"Source data is {sourceString.Length} bytes long."); SaveCompressedFile(filename, sourceString); WriteLine($"\nData saved to {filename}"); FileInfo compressedFileData = new FileInfo(filename); Write($"Compressed file is {compressedFileData.Length}"); WriteLine(" bytes long."); string recoveredString = LoadCompressedFile(filename); recoveredString = recoveredString.Substring(0, recoveredString.Length / 100); WriteLine($"\nRecovered data: {recoveredString}"); ReadKey(); } catch (IOException err) { WriteLine(err.Message); ReadKey(); }}
监控文件系统
FileSystemWatcher
- 设置属性和事件,然后将 EnableRaisingEvents 设置为 true,开始监控
FileSystemWatcher 的属性
属性 | 说明 |
Path | 设置要监控的文件位置或目录 |
NotifyFilter | NotifyFilters 枚举值组合。指定要监控哪些内容。如果指定的属性发生了变化就引发事件。可通过二元 OR 运算符来合并这些枚举值。 |
Filter | 指定要监控哪些文件的过滤器,如 *.txt |
- NotifyFilters 可能枚举值:Attributes, CreationTime, DirctoryName, FileName, LastAccess, LastWrite, Security, Size。
FileSystemWatcher 事件
Changed, Created, Deleted, Renamed
using System.IO;using Microsoft.Win32; // OpenFileDialogprivate FileSystemWatcher watcher;public MainWindow(){ InitializeComponent(); watcher.Deleted += (s, e) => AddMessage($"File: {e.FullPath} Deleted."); watcher.Renamed += (s, e) => AddMessage($"File renamed from {e.OldName} to {e.FullPath}."); watcher.Changed += (s, e) => AddMessage($"File: {e.FullPath} {e.ChangeType.ToString()}"); watcher.Created += (s, e) => AddMessage($"File: {e.FullPath} Created.");}private void AddMessage(string message){ Dispatcher.BeginInvoke(new Action(() => WatchOutput.Items.Insert(0, message)));}private void LocationBox_TextChanged(object sender, TextChangedEventArgs e){ WatchButton.IsEnabled = !string.IsNullOrEmpty(LocationBox.Text);}private void BrowseButton_Click(object sender, RoutedEventArgs e){ OpenFileDialog dialog = new OpenFileDialog(); if (dialog.ShowDialog(this) == true) LocationBox.Text = dialog.FileName;}private void WatchButton_Click(object sender, RoutedEventArgs e){ watcher.Path = System.IO.Path.GetDirectoryName(LocationBox.Text); watcher.Filter = System.IO.Path.GetFileName(LocationBox.Text); watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.Size; AddMessage($"Watching {LocationBox.Text}."); watcher.EnableRaisingEvents = true;}