====== 第十一章 文件IO ======
===== 11.1 System.IO命名空间 =====
=== 主要类 ===
| 类 | 用途 |
|----|------|
| File | 文件创建、复制、删除、移动等 |
| FileInfo | 文件详细信息和操作 |
| Directory | 目录操作 |
| DirectoryInfo | 目录详细信息和操作 |
| Path | 路径处理 |
| Stream | 字节流的抽象基类 |
| FileStream | 文件流 |
| MemoryStream | 内存流 |
| StreamReader | 字符流读取 |
| StreamWriter | 字符流写入 |
| BinaryReader | 二进制读取 |
| BinaryWriter | 二进制写入 |
===== 11.2 文件操作 =====
=== File类 ===
using System.IO;
// 检查文件是否存在
bool exists = File.Exists(@"C:\test.txt");
// 创建文件
File.Create(@"C:\newfile.txt").Close();
// 写入文本
File.WriteAllText(@"C:\test.txt", "Hello World");
File.WriteAllLines(@"C:\lines.txt", new[] { "Line1", "Line2", "Line3" });
File.AppendAllText(@"C:\test.txt", "\nAppended text");
// 读取文本
string content = File.ReadAllText(@"C:\test.txt");
string[] lines = File.ReadAllLines(@"C:\lines.txt");
// 复制、移动、删除
File.Copy(@"C:\source.txt", @"C:\dest.txt", overwrite: true);
File.Move(@"C:\old.txt", @"C:\new.txt");
File.Delete(@"C:\delete.txt");
// 文件属性
var attributes = File.GetAttributes(@"C:\test.txt");
File.SetAttributes(@"C:\test.txt", FileAttributes.Hidden);
// 时间信息
DateTime creationTime = File.GetCreationTime(@"C:\test.txt");
DateTime lastWrite = File.GetLastWriteTime(@"C:\test.txt");
DateTime lastAccess = File.GetLastAccessTime(@"C:\test.txt");
=== FileInfo类 ===
var fileInfo = new FileInfo(@"C:\test.txt");
if (fileInfo.Exists)
{
Console.WriteLine($"文件名: {fileInfo.Name}");
Console.WriteLine($"完整路径: {fileInfo.FullName}");
Console.WriteLine($"大小: {fileInfo.Length} bytes");
Console.WriteLine($"创建时间: {fileInfo.CreationTime}");
Console.WriteLine($"修改时间: {fileInfo.LastWriteTime}");
Console.WriteLine($"扩展名: {fileInfo.Extension}");
Console.WriteLine($"目录: {fileInfo.DirectoryName}");
}
// 操作方法
fileInfo.CopyTo(@"C:\backup.txt", overwrite: true);
fileInfo.MoveTo(@"C:\newlocation.txt");
fileInfo.Delete();
===== 11.3 目录操作 =====
=== Directory类 ===
// 创建目录
Directory.CreateDirectory(@"C:\NewFolder\SubFolder");
// 检查存在
bool exists = Directory.Exists(@"C:\TestFolder");
// 删除目录
Directory.Delete(@"C:\EmptyFolder"); // 空目录
Directory.Delete(@"C:\Folder", recursive: true); // 递归删除
// 获取文件
string[] files = Directory.GetFiles(@"C:\TestFolder");
string[] txtFiles = Directory.GetFiles(@"C:\TestFolder", "*.txt");
string[] allFiles = Directory.GetFiles(@"C:\TestFolder", "*.*", SearchOption.AllDirectories);
// 获取子目录
string[] subDirs = Directory.GetDirectories(@"C:\TestFolder");
// 获取所有内容
string[] entries = Directory.GetFileSystemEntries(@"C:\TestFolder");
// 目录信息
DateTime creation = Directory.GetCreationTime(@"C:\TestFolder");
string parent = Directory.GetParent(@"C:\TestFolder\Sub").FullName;
string root = Directory.GetDirectoryRoot(@"C:\TestFolder");
=== DirectoryInfo类 ===
var dirInfo = new DirectoryInfo(@"C:\TestFolder");
if (dirInfo.Exists)
{
Console.WriteLine($"目录名: {dirInfo.Name}");
Console.WriteLine($"完整路径: {dirInfo.FullName}");
Console.WriteLine($"父目录: {dirInfo.Parent?.Name}");
Console.WriteLine($"根目录: {dirInfo.Root.Name}");
Console.WriteLine($"创建时间: {dirInfo.CreationTime}");
}
// 获取文件和目录
FileInfo[] files = dirInfo.GetFiles();
FileInfo[] txtFiles = dirInfo.GetFiles("*.txt");
DirectoryInfo[] subDirs = dirInfo.GetDirectories();
// 递归获取
FileInfo[] allFiles = dirInfo.GetFiles("*.*", SearchOption.AllDirectories);
===== 11.4 路径操作 =====
using System.IO;
// 组合路径
string path1 = Path.Combine(@"C:\Folder", "file.txt"); // C:\Folder\file.txt
string path2 = Path.Combine(@"C:\Folder", "SubFolder", "file.txt");
// 获取路径各部分
string fileName = Path.GetFileName(@"C:\Folder\file.txt"); // file.txt
string fileNameNoExt = Path.GetFileNameWithoutExtension(@"C:\Folder\file.txt"); // file
string extension = Path.GetExtension(@"C:\Folder\file.txt"); // .txt
string directory = Path.GetDirectoryName(@"C:\Folder\file.txt"); // C:\Folder
string fullPath = Path.GetFullPath("file.txt"); // 完整路径
string root = Path.GetPathRoot(@"C:\Folder\file.txt"); // C:\
// 修改路径
string changeExt = Path.ChangeExtension(@"C:\file.txt", ".doc"); // C:\file.doc
// 临时路径
string tempFile = Path.GetTempFileName(); // 创建临时文件
string tempPath = Path.GetTempPath(); // 临时目录
string randomFile = Path.GetRandomFileName(); // 随机文件名
// 路径特征检查
bool isRooted = Path.IsPathRooted(@"C:\file.txt"); // true
bool isRooted2 = Path.IsPathRooted("file.txt"); // false
// 跨平台路径
string altPath = Path.Combine("folder", "subfolder", "file.txt");
// Windows: folder\subfolder\file.txt
// Linux/macOS: folder/subfolder/file.txt
===== 11.5 流(Stream) =====
=== Stream基础 ===
// 文件流
using (FileStream fs = new FileStream(@"C:\data.bin", FileMode.OpenOrCreate))
{
// 写入数据
byte[] data = Encoding.UTF8.GetBytes("Hello World");
fs.Write(data, 0, data.Length);
// 读取数据
fs.Position = 0;
byte[] buffer = new byte[fs.Length];
int bytesRead = fs.Read(buffer, 0, buffer.Length);
string text = Encoding.UTF8.GetString(buffer);
}
// FileMode枚举
// Create: 创建新文件,存在则覆盖
// CreateNew: 创建新文件,存在则异常
// Open: 打开现有文件
// OpenOrCreate: 打开或创建
// Append: 追加,若存在则定位到末尾
// Truncate: 打开并截断为零长度
=== 内存流 ===
using (MemoryStream ms = new MemoryStream())
{
// 写入
byte[] data = Encoding.UTF8.GetBytes("Memory stream test");
ms.Write(data, 0, data.Length);
// 获取字节数组
byte[] allBytes = ms.ToArray();
// 读取
ms.Position = 0;
using (StreamReader reader = new StreamReader(ms))
{
string text = reader.ReadToEnd();
Console.WriteLine(text);
}
}
// 从字节数组创建
byte[] existingData = Encoding.UTF8.GetBytes("Existing data");
using (MemoryStream ms = new MemoryStream(existingData))
{
// 读取existingData
}
===== 11.6 读写器 =====
=== StreamReader和StreamWriter ===
// 写入文本
using (StreamWriter writer = new StreamWriter(@"C:\output.txt"))
{
writer.WriteLine("第一行");
writer.WriteLine("第二行");
writer.Write("不换行");
writer.Write("继续");
}
// 追加模式
using (StreamWriter writer = new StreamWriter(@"C:\output.txt", append: true))
{
writer.WriteLine("追加的内容");
}
// 指定编码
using (StreamWriter writer = new StreamWriter(@"C:\output.txt",
append: false, encoding: Encoding.UTF8))
{
writer.WriteLine("UTF-8编码");
}
// 读取文本
using (StreamReader reader = new StreamReader(@"C:\input.txt"))
{
// 读取所有内容
string allText = reader.ReadToEnd();
// 读取一行
reader.BaseStream.Position = 0;
string line = reader.ReadLine();
// 逐行读取
reader.BaseStream.Position = 0;
string currentLine;
while ((currentLine = reader.ReadLine()) != null)
{
Console.WriteLine(currentLine);
}
}
// 异步读写
using (StreamWriter writer = new StreamWriter(@"C:\async.txt"))
{
await writer.WriteLineAsync("异步写入");
}
using (StreamReader reader = new StreamReader(@"C:\async.txt"))
{
string text = await reader.ReadToEndAsync();
}
=== BinaryReader和BinaryWriter ===
// 二进制写入
using (FileStream fs = new FileStream(@"C:\data.bin", FileMode.Create))
using (BinaryWriter writer = new BinaryWriter(fs))
{
writer.Write(123); // int
writer.Write(45.67); // double
writer.Write("Hello"); // string
writer.Write(true); // bool
writer.Write(new byte[] { 1, 2, 3 }); // byte[]
}
// 二进制读取
using (FileStream fs = new FileStream(@"C:\data.bin", FileMode.Open))
using (BinaryReader reader = new BinaryReader(fs))
{
int num = reader.ReadInt32();
double dbl = reader.ReadDouble();
string str = reader.ReadString();
bool flag = reader.ReadBoolean();
byte[] bytes = reader.ReadBytes(3);
Console.WriteLine($"{num}, {dbl}, {str}, {flag}");
}
===== 11.7 序列化 =====
=== JSON序列化(System.Text.Json) ===
using System.Text.Json;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
public string Email { get; set; }
}
// 序列化
Person person = new Person { Name = "张三", Age = 30, Email = "zhangsan@example.com" };
string json = JsonSerializer.Serialize(person);
File.WriteAllText(@"C:\person.json", json);
// 美化输出
string prettyJson = JsonSerializer.Serialize(person, new JsonSerializerOptions
{
WriteIndented = true
});
// 反序列化
string jsonContent = File.ReadAllText(@"C:\person.json");
Person deserialized = JsonSerializer.Deserialize(jsonContent);
// 集合序列化
List people = new List { person, new Person { Name = "李四", Age = 25 } };
string listJson = JsonSerializer.Serialize(people);
var peopleList = JsonSerializer.Deserialize>(listJson);
=== XML序列化 ===
using System.Xml.Serialization;
[Serializable]
public class Employee
{
public string Name { get; set; }
public int Id { get; set; }
public decimal Salary { get; set; }
[XmlIgnore]
public string Password { get; set; } // 不序列化
}
// XML序列化
Employee emp = new Employee { Name = "王五", Id = 1001, Salary = 5000 };
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Employee));
using (FileStream fs = new FileStream(@"C:\employee.xml", FileMode.Create))
{
xmlSerializer.Serialize(fs, emp);
}
// XML反序列化
using (FileStream fs = new FileStream(@"C:\employee.xml", FileMode.Open))
{
Employee deserialized = (Employee)xmlSerializer.Deserialize(fs);
Console.WriteLine(deserialized.Name);
}
===== 11.8 异步文件操作 =====
// 异步读写文件
public async Task FileOperationsAsync()
{
// 异步写入
await File.WriteAllTextAsync(@"C:\async.txt", "异步内容");
// 异步读取
string content = await File.ReadAllTextAsync(@"C:\async.txt");
// 异步流操作
using (FileStream fs = new FileStream(@"C:\largefile.txt", FileMode.Open))
using (StreamReader reader = new StreamReader(fs))
{
string line;
while ((line = await reader.ReadLineAsync()) != null)
{
Console.WriteLine(line);
}
}
}
// 异步复制大文件
public async Task CopyLargeFileAsync(string source, string destination)
{
using (FileStream sourceStream = new FileStream(source, FileMode.Open))
using (FileStream destStream = new FileStream(destination, FileMode.Create))
{
await sourceStream.CopyToAsync(destStream);
}
}
===== 练习题 =====
=== 基础练习 ===
1. **文件复制器**:编写程序将指定目录中的所有.txt文件复制到另一个目录。
2. **日志类**:实现简单的文件日志类,支持:
- 按日期创建日志文件
- 日志级别(Info、Warning、Error)
- 文件大小限制,超过则创建新文件
3. **配置管理器**:实现JSON配置文件管理器:
- 读取配置
- 保存配置
- 配置变更通知
=== 进阶练习 ===
4. **文件监视器**:使用FileSystemWatcher监视目录:
- 检测文件创建、修改、删除、重命名
- 记录所有变更到日志
- 支持过滤特定文件类型
5. **文件分割器**:实现大文件分割和合并:
- 按指定大小分割文件
- 合并分割后的文件
- 验证完整性
6. **文件加密器**:实现简单的文件加密:
- 使用AES算法
- 加密文件内容
- 解密文件内容
=== 挑战练习 ===
7. **虚拟文件系统**:在内存中实现简单的文件系统:
- 支持目录和文件
- 支持基本的CRUD操作
- 可导出到真实文件系统
8. **文件同步工具**:实现文件夹同步工具:
- 单向/双向同步
- 冲突检测和解决
- 增量同步
- 删除保护
===== 本章小结 =====
本章学习了C#文件IO操作:
- File和FileInfo类
- Directory和DirectoryInfo类
- Path类的路径操作
- Stream的概念和使用
- 文本和二进制读写器
- JSON和XML序列化
- 异步文件操作
掌握文件IO是开发实际应用程序的基础技能。