1. Introduction
看起来文件这东西很简单,创建它似乎比登天还容易:Windows 下右键点两下就完了。但在真实项目里,程序化地创建和删除文件是自动化和灵活性的关键。比如:
- 在文本编辑器里用户按「保存」— 你的代码会创建一个新文件,把用户的作品写进去。
- 事件日志服务在应用启动时自动创建日志文件。
- 压缩程序或备份工具定期创建临时文件然后再删掉它们。
- C# 的游戏做自动存档 — 创建或覆盖 save 文件。
- 还有你(或你的脚本)会自动清理旧的临时文件夹,避免把磁盘堆满。
会自动创建和删除文件,是现代 .NET 开发者的基本功之一。
2. Quick operations via File
File creation
在 C# 里可以用好几种方法创建文件。最快最直接的就是用静态类 File。来试试:
// 在当前目录创建空文件 "myfile.txt"
File.Create("myfile.txt").Close(); // FileStream 需要关闭!
Console.WriteLine("文件 'myfile.txt' 已创建.");
重要提示:
方法 File.Create 返回一个 FileStream 对象,需要关闭(Close()),否则操作系统会抱怨文件“被占用”。如果不关闭,后续对同一文件的某些操作可能会意外失败。这是经典情况: "文件被另一个进程占用",但“另一个进程”往往就是你自己没关的流。
如果文件已存在,File.Create 会覆盖它(旧的被删掉,新建一个空的)。如果文件不存在 — 就创建它。
Ну и что толку от пустого файла?
通常新文件不是用来空着的,而是要写点东西进去。为此有方便的方法:
File.WriteAllText("welcome.txt", "你好,文件世界!");
这条命令会创建文件、写入字符串,并负责优雅地把门(文件)关好,避免出事。
Проверка существования файла
在创建新文件前,检查一下它是不是已经存在是有用的。否则可能不小心把重要东西覆盖了。
if (!File.Exists("important.txt"))
{
File.WriteAllText("important.txt", "保存重要信息。");
Console.WriteLine("File created.");
}
else
{
Console.WriteLine("Such file already exists, you can come up with something else!");
}
3. Real-life example: "Saving user greeting"
Console.Write("请输入你的名字: ");
string name = Console.ReadLine();
string filename = $"{name}_greeting.txt";
string message = $"欢迎, {name}!";
// 检查这个文件是否存在
if (!File.Exists(filename))
{
File.WriteAllText(filename, message);
Console.WriteLine($"个人问候文件 {filename} 已创建.");
}
else
{
Console.WriteLine($"文件 {filename} 已存在!是否覆盖? (y/n)");
string answer = Console.ReadLine();
if (answer?.ToLower() == "y")
{
File.WriteAllText(filename, message);
Console.WriteLine($"文件 {filename} 已被覆盖.");
}
else
{
Console.WriteLine("保持原样,不做改动.");
}
}
我们在做什么:
- 检查文件是否存在(File.Exists)。
- 如果没有 — 创建并写入文本(File.WriteAllText)。
- 如果存在 — 问用户是否要覆盖。
4. File deletion
在 C# 中删除文件看起来有点黑客 feel……但其实很安全!也很简单:
Using File.Delete
File.Delete("myfile.txt");
如果文件不存在 — 没戏剧性发生!只要路径正确,什么也不会发生(不会抛错)。
Beginner traps
- 如果文件被你自己的程序(或别的程序)打开,会抛出异常。
- 如果路径写错了 — 会出现 ArgumentException。
Recommendation: always check for existence
if (File.Exists("victim.txt"))
{
File.Delete("victim.txt");
Console.WriteLine("File deleted.");
}
else
{
Console.WriteLine("Nothing to delete — such file was not found.");
}
5. Folders and files: creating a file structure
File creation в папке
string folder = "Data";
Directory.CreateDirectory(folder); // 如果没有文件夹就创建
string filename = Path.Combine(folder, "info.txt");
File.WriteAllText(filename, "这里存放秘密留言!");
重要: 如果你尝试在不存在的文件夹里创建文件,会抛异常。所以先调用 Directory.CreateDirectory(folder) 是正确的。这个方法如果文件夹已经存在也不会重复创建,所以调用是安全的。
6. Working with instances: FileInfo
对于“老派”或更进阶的场景,类 FileInfo 很实用:
FileInfo fi = new FileInfo("example.txt");
// 创建新文件(和 File.Create 一样,会创建空文件)
using (var fs = fi.Create())
{
// 如果想可以写点东西
}
Console.WriteLine($"File 'example.txt' created using FileInfo.");
通过 FileInfo 删除:
FileInfo fi = new FileInfo("oldfile.txt");
if (fi.Exists)
{
fi.Delete();
Console.WriteLine("File deleted via FileInfo.");
}
Advantages FileInfo
如果你不仅仅做创建/删除,还会频繁读取文件属性或对同一文件做多种操作,用实例方式更方便(有时候在性能上也更好)。
7. Creating and cleaning "technical files"
假设应用在文件夹 "temp_data" 中积累临时文件,我们想删除所有以 "temp_" 开头的文件。
string tempFolder = "temp_data";
Directory.CreateDirectory(tempFolder);
for (int i = 1; i <= 5; i++)
{
string tempFile = Path.Combine(tempFolder, $"temp_{i}.txt");
File.WriteAllText(tempFile, $"测试数据 {i}");
}
Console.WriteLine("已创建 5 个临时文件。");
// 现在删除所有 temp_*.txt
foreach (string file in Directory.GetFiles(tempFolder, "temp_*.txt"))
{
File.Delete(file);
Console.WriteLine($"已删除文件: {file}");
}
对自动清理旧临时文件很管用。
8. Important details: exceptions and security
可能出的问题:
- 没有写入/删除权限(例如在 C:\Windows)
- 文件被其他程序(或你自己)占用
- 路径含有不允许的字符(例如 *?<>)
- 在你检查和删除之间文件被别的进程删掉了(是会有这种事的)
如何防护
在生产代码里,这类操作一般都用 try-catch 包起来:
try
{
File.Delete("trickyfile.txt");
Console.WriteLine("File deleted.");
}
catch (UnauthorizedAccessException ex)
{
Console.WriteLine("No permission to delete the file.");
}
catch (IOException ex)
{
Console.WriteLine("The file might be occupied by another process.");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
9. Useful nuances
Files that are always under control
- 使用 Path.Combine 来拼接路径。这样不会出现多余或缺失的斜杠,代码更跨平台。
- 在创建/删除前检查文件是否存在,避免惊喜。
- 在生产或特别是“多人使用”的应用里用 try-catch 包裹你的代码。
- 对同一个文件频繁操作用 FileInfo,一次性操作用 File。
- 不要把文件打开着比必要时间长。文件还开着?问问自己:"为什么还开着?" 然后关掉它!能用 using 的地方就用它。
Technical cheat sheet
| 操作 | 方法 | 备注 |
|---|---|---|
| 创建空文件 | |
返回 FileStream,需要关闭 |
| 写文本到文件 | |
创建文件或覆盖 |
| 检查是否存在 | |
返回 bool |
| 删除文件 | |
如果文件不存在不会抛异常 |
| 在文件夹中创建文件 | |
保证文件夹存在 |
| 用 FileInfo 操作 | |
用于多次操作 |
10. Common errors when working with files
错误 №1: 忘记在 File.Create 之后关闭流。
很多新手用 File.Create 创建文件,但不关闭返回的流。结果后面的代码就“看不到”文件了——好像掉进了平行宇宙。要显式关闭流(Close())或用 using。
错误 №2: 试图在不存在的文件夹里创建文件。
常见的坑是试图在还没创建的目录里建文件。别忘了提前调用 Directory.CreateDirectory。这是绝对安全的:不会多创建什么,必要的文件夹会出现。
错误 №3: 在删除前不检查。
有时人们直接调用 File.Delete,不检查文件是否存在。这个方法在文件不存在时不会报错,但如果路径写错或没有权限 — 异常是会发生的。最好提前处理这些情况。
错误 №4: 混淆 File.Delete 和 Directory.Delete。
File.Delete 只对文件有效,Directory.Delete 用于目录。用 File.Delete 去删目录就像用牙刷去抛光砖块:技术上可能搞不定,但并不合适。
GO TO FULL VERSION