CodeGym /课程 /C# SELF /静态类 File 和 Directory

静态类 File 和 Directory

C# SELF
第 39 级, 课程 0
可用

1. 介绍

直接用流(StreamReader, StreamWriter, FileStream)很有用,尤其当你需要在低层控制读/写过程:比如分块写入或者分片处理大文件。

但在实际开发中,经常只是想知道:“这个文件存在吗?”,“把文件从这儿复制到那儿”,“删除文件”,“获取文件夹里所有 .txt 文件”等。为这些场景,Microsoft 提供了两个通用工具:静态类 File 和 Directory。静态的意思是你不需要创建实例,直接通过类名调用方法。

生活类比

如果流是你拿着笔,一笔一划地写字,那么 File 和 Directory 就像你的办公桌和抽屉:你可以“瞬间”打开抽屉(Directory),从里头拿出纸条(File.ReadAllText),把纸条扔掉(File.Delete),或者直接把整个抽屉挪到房间另一头(Directory.Move)。简单的事用简单的方法。

2. 类 File:它是什么,有什么用

File 提供了一组方便的静态方法,覆盖了常见的文件操作。

最常用的方法

方法 说明
File.Exists(path)
检查指定路径的文件是否存在
File.ReadAllText(path)
把整个文件作为文本读取
File.ReadAllLines(path)
把文件的所有行读入数组
File.WriteAllText(path, text)
重写文件并写入文本
File.AppendAllText(path, text)
在文件末尾追加文本
File.Copy(source, destination)
复制文件
File.Delete(path)
删除文件
File.Move(source, destination)
移动或重命名文件
File.Open/Read/Write/Create
打开流以进行复杂操作

快速示例:检查文件并读取

string filePath = "data.txt";

if (File.Exists(filePath))
{
    string content = File.ReadAllText(filePath);
    Console.WriteLine("文件内容:");
    Console.WriteLine(content);
}
else
{
    Console.WriteLine("未找到文件!");
}

看到了吗?简单场景下不用手动管理流!

3. 类 Directory:轻松管理文件夹

如果 File 处理单个文件,Directory 则处理文件夹(目录)。

主要任务

方法 说明
Directory.Exists(path)
检查文件夹是否存在
Directory.CreateDirectory(path)
创建文件夹(会一并创建中间路径)
Directory.Delete(path)
删除文件夹(可以包含子目录)
Directory.GetFiles(path)
获取文件夹中的文件列表
Directory.GetDirectories(path)
获取子目录列表
Directory.Move(source, destination)
移动或重命名文件夹
Directory.GetCurrentDirectory()
获取应用的当前工作目录

示例:创建文件夹并保存文件

string dirPath = "Results";
if (!Directory.Exists(dirPath))
{
    Directory.CreateDirectory(dirPath);
    Console.WriteLine("文件夹 'Results' 已创建。");
}

string filePath = Path.Combine(dirPath, "summary.txt");
File.WriteAllText(filePath, "汇总数据:...");

Console.WriteLine($"文件 {filePath} 已写入。");

4. 使用 File 和 Directory 的典型场景

基本方法看起来无聊,除非你看到它们的用例!我们通过几个例子把它们放到实际场景里,同时继续扩展我们的示例应用(假设我们做一个简单的待办事项系统 — todo-list,结果保存在文件里)。

保存数据到文件(替换旧文件)

// 把待办项保存到文件
string[] todos = { "买面包", "给医生打电话", "做 C# 的家庭作业" };
string filePath = "todo.txt";
File.WriteAllLines(filePath, todos);

Console.WriteLine("待办列表已保存。");

从文件加载数据

// 如果文件存在就加载任务
if (File.Exists(filePath))
{
    string[] loadedTodos = File.ReadAllLines(filePath);
    Console.WriteLine("你的待办列表:");
    foreach (var task in loadedTodos)
    {
        Console.WriteLine("- " + task);
    }
}
else
{
    Console.WriteLine("你还没有待办列表。");
}

添加新任务(不覆盖文件)

string newTask = "带狗去散步";
File.AppendAllText(filePath, newTask + Environment.NewLine);
Console.WriteLine("任务已添加!");

复制和备份文件

string backupPath = "todo_backup.txt";
File.Copy(filePath, backupPath, overwrite: true);
Console.WriteLine("待办列表的备份已创建。");

移动(或重命名)文件

string archivePath = "todo_archive.txt";
File.Move(filePath, archivePath);
Console.WriteLine("待办列表已归档(重命名)。");

删除文件

if (File.Exists(archivePath))
{
    File.Delete(archivePath);
    Console.WriteLine("归档已删除 — 释放空间!");
}

5. 操作文件夹:示例

创建目录层级

string path = Path.Combine("Reports", "2024", "June");
Directory.CreateDirectory(path);
Console.WriteLine($"文件夹 {path} 已创建(包含中间目录)。");

获取文件和文件夹列表

string dirPath = "Reports";
if (Directory.Exists(dirPath))
{
    string[] files = Directory.GetFiles(dirPath);
    Console.WriteLine("文件夹中的文件:");
    foreach (var file in files)
    {
        Console.WriteLine(file);
    }

    string[] subDirs = Directory.GetDirectories(dirPath);
    Console.WriteLine("子目录:");
    foreach (var dir in subDirs)
    {
        Console.WriteLine(dir);
    }
}

按掩码过滤文件(仅 txt)

string[] txtFiles = Directory.GetFiles(dirPath, "*.txt");
Console.WriteLine("只有 .txt 文件:");
foreach (var file in txtFiles)
{
    Console.WriteLine(file);
}

递归遍历(所有子目录中的文件)

string[] allFiles = Directory.GetFiles(dirPath, "*.*", SearchOption.AllDirectories);
Console.WriteLine("所有嵌套文件夹中的文件:");
foreach (var file in allFiles)
{
    Console.WriteLine(file);
}

移动和删除目录

string from = "OldReports";
string to = "Archive/OldReports";
if (Directory.Exists(from))
{
    Directory.Move(from, to);
    Console.WriteLine($"文件夹 {from} 已移到 {to}");
}

if (Directory.Exists(to))
{
    Directory.Delete(to, recursive: true); // true:删除内部所有内容
    Console.WriteLine($"文件夹 {to} 已删除(包含所有内容)。");
}

6. 有用的细节

与路径配合:类 Path

处理文件和文件夹时,经常需要拼接完整路径、组合目录名和文件名、解析扩展名、检查非法字符。为此用辅助类 Path。

示例

string folder = "Results";
string filename = "week1.txt";
string fullPath = Path.Combine(folder, filename); // 安全合并!
Console.WriteLine(fullPath); // "Results/week1.txt"(在 Windows 上可能是 "\")
  • 获取文件扩展名: Path.GetExtension(fullPath)
  • 获取不带路径的文件名: Path.GetFileName(fullPath)

用 Path.Combine 替代字符串拼接 — 对跨平台应用更安全。

“一次性”方法 vs 流式变体

很多 File 和 Directory 的方法(例如 File.ReadAllText, File.WriteAllText, Directory.GetFiles)都做“整件事”:一次性读取/写入/获取文件列表。非常方便,但不适合超大文件或超大目录,可能会耗尽内存。如果要处理 GB 级别的数据,应该用流类(StreamReader, StreamWriter, FileStream 等)或分块处理。

什么时候用 File/Directory,什么时候用流类

场景 建议使用
需要检查文件/文件夹是否存在
File.Exists, Directory.Exists
读取/写入小文件(整体)
File.ReadAllText, WriteAllText
在文件末尾追加文本
File.AppendAllText
获取目录中的文件列表
Directory.GetFiles
复制、删除、移动文件
File.Copy/Delete/Move
复制/删除整个文件夹 Directory.Delete/Move/Copy(Copy 需要第三方库)
分块处理非常大的文件 流类(StreamReader, FileStream)

实际意义和使用场景

  • 快速加载/保存配置、设置、JSON/XML 文件。
  • 日志系统(把日志写入磁盘)。
  • 简单的备份工具和数据迁移。
  • 扫描多媒体、照片、文档的文件夹。
  • 用户场景:加载模板、导入/导出、生成报告等。

面试题里也常会让你用这些类来做事:比如“实现一个函数,计算目录下所有 .txt 文件的总大小”,或“把文件备份到另一个文件夹”等。

快速参考:什么时候用哪个方法

graph TD
    A[你想做什么?]
    A -->|检查存在性| B[File.Exists 或 Directory.Exists]
    A -->|整体读/写文件| C[File.ReadAllText/WriteAllText]
    A -->|向文件追加数据| D[File.AppendAllText]
    A -->|处理文件夹| E[Directory.CreateDirectory, GetFiles, GetDirectories]
    A -->|复制/删除/移动文件| F[File.Copy/Delete/Move]
    A -->|复制/删除整个文件夹| G[Directory.Delete/Move]

7. 特性和常见错误

存在性检查与“竞态条件”。即使你先检查了文件/文件夹是否存在,在实际操作之前另一个进程也可能改变它们。所以即便检查过,也要用 try-catch 来捕获可能的问题!

权限问题。如果应用没有足够的读/写/删除权限,方法会抛出 UnauthorizedAccessException。

路径过长。路径最大长度(老 Windows 通常是 260 字符;在 .NET 9 中限制放宽了,但仍需注意)。

异常处理。像 File.ReadAllText 或 Directory.GetFiles 这样的“整件事”方法不会容忍错误:如果文件/文件夹不存在就会抛异常。把它们包在 try-catch 中,或者事先检查存在性。

2
任务
C# SELF, 第 39 级, 课程 0
已锁定
创建和删除文件夹
创建和删除文件夹
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION