C#文件操作指南
·
C#文件操作全面总结
一、文件操作的三种主要方式
在C#中处理文件有三种层次的方法,从简单到复杂分别是:
1. File类(最简单) - 快餐店
csharp
// 就像去快餐店,告诉服务员你要什么,他帮你完成所有步骤
File.WriteAllText("文件.txt", "内容"); // 一次性完成
string content = File.ReadAllText("文件.txt"); // 一次性读取
特点:一行代码完成读写,适合简单场景
2. FileStream类(中间层) - 自助餐厅
csharp
// 像在自助餐厅,自己操作每个步骤
using (FileStream fs = new FileStream("文件.txt", FileMode.OpenOrCreate))
{
byte[] data = Encoding.UTF8.GetBytes("内容");
fs.Write(data, 0, data.Length); // 自己控制写入
// ... 可以自己控制流的位置、分段处理等
}
特点:可以控制细节,适合需要自定义处理的场景
3. BinaryReader/Writer(专业层) - 专业厨房
csharp
// 像专业厨师,处理各种特殊食材
using (BinaryWriter bw = new BinaryWriter(fs))
{
bw.Write(100); // 直接写整数
bw.Write(true); // 直接写布尔值
bw.Write(10.5); // 直接写浮点数
}
特点:直接处理各种数据类型,性能最好
二、File类操作详解(最常用)
2.1 基本文件操作
csharp
// 1. 创建文件(返回FileStream)
FileStream fs = File.Create("test.txt");
fs.Close(); // 一定要关闭!
// 2. 复制文件
File.Copy("源文件.txt", "目标文件.txt");
// 3. 移动/重命名文件
File.Move("旧名字.txt", "新名字.txt");
// 4. 删除文件
File.Delete("要删除的文件.txt");
// 5. 判断文件是否存在
if (File.Exists("文件.txt"))
{
Console.WriteLine("文件存在");
}
2.2 读写文本文件
csharp
// 写入整个字符串
File.WriteAllText("日记.txt", "今天学习C#很开心!");
// 追加内容(不覆盖原有内容)
File.AppendAllText("日记.txt", "\n明天继续努力!");
// 按行写入数组
string[] lines = { "第一行", "第二行", "第三行" };
File.WriteAllLines("多行.txt", lines);
// 读取整个文件
string content = File.ReadAllText("日记.txt");
// 按行读取(返回字符串数组)
string[] allLines = File.ReadAllLines("多行.txt");
foreach (string line in allLines)
{
Console.WriteLine(line);
}
2.3 读写二进制数据
csharp
// 字符串转字节数组
byte[] data = Encoding.UTF8.GetBytes("你好世界");
// 写入字节数组
File.WriteAllBytes("二进制.bin", data);
// 读取字节数组
byte[] readData = File.ReadAllBytes("二进制.bin");
string text = Encoding.UTF8.GetString(readData);
Console.WriteLine(text); // 输出:你好世界
三、FileStream流式操作(更灵活)
3.1 FileMode模式(非常重要!)
| 模式 | 作用 | 如果文件存在 | 如果文件不存在 |
|---|---|---|---|
| Create | 创建 | 覆盖(清空) | 创建新文件 |
| CreateNew | 创建 | 报错 | 创建新文件 |
| Open | 打开 | 打开 | 报错 |
| OpenOrCreate | 打开或创建 | 打开 | 创建新文件 |
| Append | 追加 | 打开(定位到末尾) | 创建新文件 |
| Truncate | 打开并清空 | 清空内容 | 报错 |
3.2 FileAccess权限
csharp
// 只读权限(只能读不能写)
FileStream fs1 = new FileStream("文件.txt", FileMode.Open, FileAccess.Read);
// 只写权限(只能写不能读)
FileStream fs2 = new FileStream("文件.txt", FileMode.Create, FileAccess.Write);
// 读写权限(既能读又能写)
FileStream fs3 = new FileStream("文件.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite);
3.3 实际使用示例
csharp
// 创建文件流(推荐使用using自动关闭)
using (FileStream fs = new FileStream("数据.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
// 写入数据
string message = "Hello, FileStream!";
byte[] buffer = Encoding.UTF8.GetBytes(message);
fs.Write(buffer, 0, buffer.Length);
// 重置流位置到开头(才能读取刚写入的数据)
fs.Position = 0;
// 读取数据
byte[] readBuffer = new byte[fs.Length];
fs.Read(readBuffer, 0, readBuffer.Length);
string result = Encoding.UTF8.GetString(readBuffer);
Console.WriteLine(result); // 输出:Hello, FileStream!
// 不需要手动Close(),using会自动调用
}
四、BinaryReader/Writer(高性能二进制)
4.1 BinaryWriter写入各种类型
csharp
using (FileStream fs = new FileStream("游戏存档.dat", FileMode.Create))
using (BinaryWriter bw = new BinaryWriter(fs))
{
// 可以直接写入各种类型,不需要转字节数组
bw.Write(100); // 整数
bw.Write(95.5f); // 浮点数
bw.Write(true); // 布尔值
bw.Write("玩家姓名"); // 字符串
bw.Write(new byte[] { 1, 2, 3, 4 }); // 字节数组
}
4.2 BinaryReader读取各种类型
csharp
using (FileStream fs = new FileStream("游戏存档.dat", FileMode.Open))
using (BinaryReader br = new BinaryReader(fs))
{
// 必须按照写入的顺序和类型读取!
int score = br.ReadInt32(); // 读取整数
float health = br.ReadSingle(); // 读取浮点数
bool isAlive = br.ReadBoolean(); // 读取布尔值
string name = br.ReadString(); // 读取字符串
byte[] data = br.ReadBytes(4); // 读取4个字节
Console.WriteLine($"玩家:{name}, 分数:{score}, 生命值:{health}");
}
4.3 安全读取技巧
csharp
// 使用PeekChar()检查是否还有数据
while (br.PeekChar() != -1) // -1表示到文件末尾
{
try
{
// 尝试读取,类型要匹配
int data = br.ReadInt32();
Console.WriteLine(data);
}
catch (EndOfStreamException)
{
// 文件读取完毕
break;
}
}
五、路径处理技巧
5.1 相对路径写法
csharp
// 当前目录下的文件 string path1 = "data.txt"; // 当前文件夹 string path2 = @".\data.txt"; // 当前文件夹(明确写法) string path3 = @"./data.txt"; // 当前文件夹(另一种写法) // 上级目录 string path4 = @"..\data.txt"; // 上一级文件夹 string path5 = @"..\..\data.txt"; // 上两级文件夹 // 子目录 string path6 = @"subfolder\data.txt"; // 子文件夹
5.2 使用Path类处理路径
csharp
// 合并路径(自动处理斜杠)
string fullPath = Path.Combine("文件夹", "子文件夹", "文件.txt");
// 获取路径各部分
string directory = Path.GetDirectoryName(fullPath); // 目录
string filename = Path.GetFileName(fullPath); // 文件名
string extension = Path.GetExtension(fullPath); // 扩展名
string noExt = Path.GetFileNameWithoutExtension(fullPath); // 无扩展名
// 临时文件
string tempFile = Path.GetTempFileName(); // 获取临时文件名
六、编码问题(重要!)
6.1 常见编码
csharp
// 写入时指定编码
File.WriteAllText("文件.txt", "中文内容", Encoding.UTF8);
// 读取时指定编码
string content = File.ReadAllText("文件.txt", Encoding.UTF8);
// 常用编码
Encoding.UTF8 // UTF-8编码(最常用,支持中文)
Encoding.ASCII // ASCII编码(只支持英文)
Encoding.Unicode // Unicode编码(UTF-16)
Encoding.Default // 系统默认编码
6.2 编码转换
csharp
// 字符串转字节数组
string text = "你好";
byte[] utf8Bytes = Encoding.UTF8.GetBytes(text); // UTF-8编码
byte[] gbkBytes = Encoding.GetEncoding("GBK").GetBytes(text); // GBK编码
// 字节数组转字符串
string fromUtf8 = Encoding.UTF8.GetString(utf8Bytes);
string fromGbk = Encoding.GetEncoding("GBK").GetString(gbkBytes);
七、最佳实践和常见错误
7.1 必须使用using或手动Close
csharp
// ❌ 错误做法:忘记关闭文件
FileStream fs = new FileStream("文件.txt", FileMode.Create);
// 操作文件...
// 忘记 fs.Close(),文件可能被锁定
// ✅ 正确做法1:使用using(推荐)
using (FileStream fs = new FileStream("文件.txt", FileMode.Create))
{
// 操作文件...
} // 自动关闭
// ✅ 正确做法2:手动Close
FileStream fs = null;
try
{
fs = new FileStream("文件.txt", FileMode.Create);
// 操作文件...
}
finally
{
if (fs != null)
fs.Close(); // 确保关闭
}
7.2 异常处理
csharp
try
{
// 文件操作
File.WriteAllText("重要数据.txt", data);
}
catch (FileNotFoundException ex)
{
Console.WriteLine("文件没找到:" + ex.Message);
}
catch (IOException ex)
{
Console.WriteLine("IO错误:" + ex.Message);
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("没有权限:" + ex.Message);
}
catch (Exception ex)
{
Console.WriteLine("其他错误:" + ex.Message);
}
7.3 性能考虑
csharp
// 对于大文件,使用流式处理
using (FileStream fs = new FileStream("大文件.txt", FileMode.Open))
{
byte[] buffer = new byte[4096]; // 4KB缓冲区
int bytesRead;
while ((bytesRead = fs.Read(buffer, 0, buffer.Length)) > 0)
{
// 处理buffer中的数据
ProcessChunk(buffer, bytesRead);
}
}
八、选择指南
| 场景 | 推荐方式 | 理由 |
|---|---|---|
| 简单文本读写 | File.ReadAllText/WriteAllText | 最简单,一行代码搞定 |
| 大文件处理 | FileStream + 缓冲区 | 可以分段处理,内存占用小 |
| 读写结构化数据 | BinaryReader/Writer | 直接读写各种类型,性能好 |
| 需要灵活控制 | FileStream | 可以控制位置、权限等细节 |
| 追加内容 | File.AppendAllText 或 FileMode.Append | 专门用于追加 |
| 临时文件 | Path.GetTempFileName() + File类 | 系统管理临时文件 |
九、一句话总结
-
File类:最简单,适合快速操作
-
FileStream:最灵活,可以控制细节
-
Binary:性能最好,适合结构化数据
记住黄金法则:读取用什么方式,写入就用什么方式,特别是二进制文件要严格匹配类型和顺序!
更多推荐


所有评论(0)