dotnet 文件操作
Path
更改扩展名,连接路径
获取目录信息,文件名,扩展名,绝对路径
string path = @"C:\Users\Lenovo\Pictures";
string fileName = "lyy.jpg";
string fileNameNew = Path.Combine(path, fileName);//C:\Users\Lenovo\Pictures\lyy.jpg
var root = Path.GetPathRoot(path);// root=="C:\"
string temppath = Path.GetTempFileName();//在C:\Users\Lenovo\AppData\Local\Temp创建一个xxx.tmp文件
string filename = Path.GetFileName(fileNameNew);//lyy.jpg,如果这个路径没文件,返回最后一个目录名
string filefullpath = Path.GetFullPath("./Program.cs");//D:\My_Codes\C#base\WinformIO\bin\Debug\Program.cs
string ext = Path.GetExtension(fileNameNew).ToLower();//扩展名 ".jpg"
string dirName = Path.GetDirectoryName(fileNameNew);//C:\Users\Lenovo\Pictures
File
提供创建,复制,删除,移动和打开文件的静态方法
| 创建文件 | File.Create() | File.Create(@"C:\test\newFile.txt").Close(); | 创建指定路径的空文件,创建后需调用 Close() 释放资源(或用 using 语句)。 |
|---|---|---|---|
| 复制文件 | File.Copy() | File.Copy(@"C:\test\source.txt", @"C:\test\copy.txt"); | 将 “源文件” 复制到 “目标路径”,若目标文件已存在会报错(可加第三个参数 true 覆盖)。 |
| 删除文件 | File.Delete() | File.Delete(@"C:\test\oldFile.txt"); | 删除指定路径的文件,若文件不存在不会报错(静默执行)。 |
| 移动文件 | File.Move() | File.Move(@"C:\test\oldPath.txt", @"C:\newDir\newName.txt"); | 剪切文件到新路径,支持同时修改文件名;若目标文件已存在会报错。 |
| 打开文件 | File.Open() | using (var stream = File.Open(@"C:\test\openFile.txt", FileMode.Open)) | 以指定模式(如打开、创建后打开)打开文件,返回文件流用于读写;需用 using 自动释放资源。 |
FileInfo
提供创建,复制,删除,移动和打开文件的实例方法,并协助创建FileSteam
| 操作类型 | 实例方法 | 代码示例 | 说明 |
|---|---|---|---|
| 创建文件 | Create() | csharp var fileInfo = new FileInfo(@"C:\test\file.txt"); using (var stream = fileInfo.Create()) | 创建文件(若已存在则覆盖),返回返回 FileStream 对象,需用 using 释放资源。 |
| 复制文件 | CopyTo() | csharp var fileInfo = new FileInfo(@"C:\test\source.txt"); // 复制到目标路径,第三个参数指定是否覆盖(默认 false) fileInfo.CopyTo(@"C:\test\copy.txt", overwrite: true); 如果overwrite 为 false,有已有文件报异常 | 将当前文件复制到新路径,支持指定参数控制是否覆盖已有文件。 |
| 删除文件 | Delete() | csharp var fileInfo = new FileInfo(@"C:\test\old.txt"); fileInfo.Delete(); | 删除当前实例绑定的文件,若文件不存在则无操作(不抛异常)。 |
| 移动文件 | MoveTo() | csharp var fileInfo = new FileInfo(@"C:\test\old.txt"); fileInfo.MoveTo(@"C:\newDir\new.txt"); | 移动文件到新路径(可同时重命名),若目标文件已存在则抛异常。 |
| 打开文件 | Open() | csharp var fileInfo = new FileInfo(@"C:\test\file.txt"); using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read)) | 以指定 FileMode(打开模式)和 FileAccess(访问权限)打开文件,返回文件流。 |
FileMode
打开文件方式
Create CreateNew Append Open OpenOrCreate
| 枚举值 | 含义与行为 | 典型场景 |
|---|---|---|
FileMode.Open |
仅打开已存在的文件。 ❌ 若文件不存在,抛出 FileNotFoundException。✅ 指针位于开头。 |
读取/修改已有文件(如配置文件、日志) |
FileMode.Create |
不存在则创建,已存在则覆盖(清空内容)。 ✅ 最终得到空文件,指针位于开头。 |
创建新文件(覆盖同名文件,如临时文件) |
FileMode.CreateNew |
仅创建新文件。 ❌ 若文件已存在,抛出 IOException。✅ 新文件指针位于开头。 |
确保文件唯一(如不可重复的日志、编号文件) |
FileMode.Append |
打开文件并将指针定位到末尾(仅用于写入)。 ❌ 若文件不存在,抛出 FileNotFoundException。 |
日志记录(往末尾添加新内容) |
FileMode.Truncate |
打开已存在文件并清空内容(保留文件本身)。 ❌ 若文件不存在,抛出 FileNotFoundException。 |
重置文件内容(如清空缓存、重新写入数据) |
FileMode.OpenOrCreate |
存在则打开(指针在开头),不存在则创建(空文件)。 ✅ 不覆盖已有文件。 |
不确定文件是否存在时(如本地缓存文件) |
FileAccess
文件访问权限 Read Write ReadWrite 创建 复制 删除 移动 打开 追加 写入 读取
Directory DirectoryInfo
Directory 通过目录子目录进行创建,移动,删除,枚举的静态方法
string[] fileStrs = Directory.GetFile(@"D:\desktop\image");得到的是文件列表字符串

DirectoryInfo 通过目录子目录进行创建,移动,删除,枚举的实例方法
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] files = di.GetFiles();得到的是才是文件
获取指定目录的子目录,文件列表


FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog() == DialogResult.OK)
{
string folderPath = fbd.SelectedPath;//文件夹路径,C:\\Users\\Lenovo\\Desktop\\TestFile
string[] folders = Directory.GetDirectories(folderPath);//子目录列表 C:\\Users\\Lenovo\\Desktop\\TestFile\\level1-1,C:\\Users\\Lenovo\\Desktop\\TestFile\\level1-2
listBox1.Items.Clear();
foreach (string path in folders)
{
DirectoryInfo di = new DirectoryInfo(path);
listBox1.Items.Add(di.FullName);//C:\\Users\\Lenovo\\Desktop\\TestFile
}
}
DirectoryInfo di 显示


string folderPath = listBox1.SelectedItem.ToString();//选择文件夹的路径
DirectoryInfo di = new DirectoryInfo(folderPath);
FileInfo[] files = di.GetFiles();//获取指定文件夹下的文件列表
listBox2.Items.Clear();
foreach (FileInfo f in files)
{
listBox2.Items.Add(f.Name);
}

DirectoryInfo t1 = di.CreateSubdirectory("sub1/sub2");在level1-1目录中先创建sub1,再在sub1里创建sub2
string path = @"C:\Users\Lenovo\Pictures";
string fileName = "lyy.jpg";
string fileNameNew = Path.Combine(path, fileName);//C:\Users\Lenovo\Pictures\lyy.jpg
if (Directory.Exists(path))//判断目录存在
{
string[] files = Directory.GetFiles(path);//获取文件列表 string[]{C:\Users\Lenovo\Pictures\lyy.jpg ,C:\Users\Lenovo\Pictures\xyy.jpg...}
int i = 0;
foreach (string fPath in files)
{
string ext = Path.GetExtension(fPath).ToLower();//扩展名
if (ext == ".jpg" || ext == ".png")
{
Image img = Image.FromFile(fPath);//加载图片
imageList1.Images.Add(img);
ListViewItem li = new ListViewItem();
li.Text = Path.GetFileName(fPath);
li.ImageIndex = i;
listView1.Items.Add(li);
i++;
}
}
}
或者
DirectoryInfo directoryInfo = new DirectoryInfo(path);
int i = 0;
if (directoryInfo.Exists)
{
FileInfo[] files = directoryInfo.GetFiles();
foreach (var file in files)
{
string ext = file.Extension.ToLower();
if (ext == ".jpg" || ext == ".png")
{
Image img = Image.FromFile(file.FullName);//加载图片
imageList1.Images.Add(img);
ListViewItem li = new ListViewItem();
li.Text = file.Name;
li.ImageIndex = i;
listView1.Items.Add(li);
i++;
}
}
}
Stream
提供字节序列的一般视图
提供了以字节形式从流中读取内容
StreamReader 和 StreamWriter帮我们实现在六上读写字符串的功能
MemoryStream存储在内存的字节流
FIlleStream 存储在文件系统的字节流
BufferedStream 为其他流提供缓冲的流
| 属性名 | 说明 |
|---|---|
| CanRead | 指示当前流是否支持读取操作。 |
| CanSeek | 指示当前流是否支持查找(定位到流中特定位置)功能。 |
| CanWrite | 指示当前流是否支持写入操作。 |
| Length | 获取流的长度,单位为字节。 |
| Position | 获取或设置当前流中的位置。 |
| 方法名 | 说明 |
|---|---|
| Close() | 关闭当前流并释放与之关联的所有资源。 |
| Flush() | 清除流的所有缓冲区,使缓冲数据写入到基础设备(如磁盘)。 |
| Read() | 从当前流读取字节序列,流的位置会随读取的字节数提升。 |
| Seek() | 设置当前流中的位置。 |
| Write() | 向当前流中写入字节序列,流的当前位置会随写入的字节数提升。 |
TextReader 基本说明
是用于读取有序字符系列的抽象类,不能直接实例化。
实现了 IDisposable 接口,可通过 using 语句自动释放资源。
派生类:
StreamReader:从流(如文件流)中读取字符。
StringReader:从字符串中读取字符。
| 方法名 | 说明 |
|---|---|
| Close() | 关闭 TextReader 并释放相关系统资源。 |
| Dispose() | 释放 TextReader 对象的所有资源。 |
| Peek() | 读取下一个字符,不改变读取器状态或字符源。 |
| Read() | 读取下一个字符,读取位置后移一个字符。 |
| Read(Char[], int32, int32) | 从当前读取器读取指定数目的字符,从指定索引开始写入缓冲区。 |
| ReadAsync(Char[], Int32, Int32) | 异步读取字符(图片中信息未完全显示,推测为异步版读取方法)。 |
| ReadLine() | 读取一行字符,以字符串形式返回。 |
| ReadToEnd() | 读取从当前位置到末尾的所有字符,以一个字符串返回。 |
string path = @"C:\Users\Lenovo\Desktop\TestFile\Hello.cs";
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\Hello(1).txt";//必须是要带文件名
//string path = @"C:\Users\Lenovo\Desktop\TestFile\c#基础.pptx";
//string pathto = @"C:\Users\Lenovo\Desktop\TestFile\c#基础11.pptx"; //不行
//string path = @"C:\Users\Lenovo\Desktop\TestFile\37 Chart控件介绍-1.mp4";
//string pathto = @"C:\Users\Lenovo\Desktop\TestFile\37 Chart控件介绍-11.mp4";//不行
//string path = @"D:\NewImgs\aaaa.jpg";
//string pathto = @"D:\NewImgs02\aaaa1.jpg"; //不行
char[] data = new char[1024];
using (StreamReader dr = new StreamReader(path))//线程不安全
{
using (StreamWriter sw = new StreamWriter(pathto))
{
while (true)
{
int rcount = dr.Read(data, 0, data.Length);//每次读1024字符
if (rcount == 0) break;
sw.Write(data, 0, rcount);
}
}
}
FileStream 功能与操作方式
用于对文件系统中的文件进行读取、写入、打开和关闭操作。
同步操作方法:Read、Write、CopyTo、Flush。
异步操作方法:ReadAsync、WriteAsync、CopyToAsync、FlushAsync。
异步方法优势:执行占用大量资源的文件操作时,不会阻塞主线程,提升程序响应性。
| 构造函数签名 | 参数说明 |
|---|---|
| FileStream(String, FileMode) | 第一个参数为文件路径,第二个参数为文件模式(指定文件打开 / 创建方式) |
| FileStream(String, FileMode, FileAccess) | 第三个参数为文件访问方式(读、写、读写) |
| FileStream(String, FileMode, FileAccess, FileShare) | 第四个参数为文件共享方式(指定其他进程如何访问该文件) |
| FileStream(String, FileMode, FileAccess, FileShare, Int32) | 第五个参数为缓冲区大小 |
string path = @"C:\Users\Lenovo\Desktop\TestFile\wx-dy.mp4";
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\wx-dy111.mp4";
bytes = new byte[size];
using (fr = new FileStream(path, FileMode.Open, FileAccess.Read))
{
using (fw = new FileStream(pathto, FileMode.Create, FileAccess.Write))
{
int count = fr.Read(bytes, 0, size);//每次读,头指针指到上次读的地方
while (count > 0)
{
fw.Write(bytes, 0, count);
count = fr.Read(bytes, 0, size);
}
}
}
MemoryStreamMemoryStream
创建一个流,其后备存储为内存。内存流 数据以无符号字节数组的形式保存在内存中,系统可以直接访问这些封装的数据而不必读取磁盘文件。
更加贴近底层数据,读取的效率更高 (读取速度更快,和文件流的主要区别),内存流可以降低系统对临时缓冲区和临时文件的需要。
因此我们编程中常常用内存流作为中转,与其他流进行数据交换。(如利用 MemoryStream 操作文件,然后传给 FileStream 中)
string path = @"C:\Users\Lenovo\Desktop\TestFile\wx-dy.mp4";
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\wx-dybyMemoryStream.mp4";
bytes = new byte[size];
MemoryStream ms = new MemoryStream(size);
using (fr = new FileStream(path, FileMode.Open, FileAccess.Read))
{
int count = fr.Read(bytes, 0, size);
while (count > 0)
{
ms.Write(bytes, 0, count);
count = fr.Read(bytes, 0, size);
}
}
//写入流
using (fw = new FileStream(pathto, FileMode.Create, FileAccess.Write))
{
ms.WriteTo(fw);
}
BufferedStream 核心作用
是缓冲流,为另一个流添加缓冲区以进行读写操作。
提升读写性能:通过内存中的字节块(缓冲区)缓存数据,减少对操作系统的调用次数,尤其在大文件操作场景下效率优于 StreamReader 和 StreamWriter。
| 效率优势 | 比 StreamReader、StreamWriter 效率更高,尤其适用于大文件 | 大文件的二进制读写(如视频、压缩包)、对性能要求高的字节流操作 |
|---|---|---|
| 通用性 | 可处理各类文件(不仅限于文本文件),弥补 StreamReader/StreamWriter 仅能逐行操作文本的局限 | 非文本文件(如图片、音频)的字节级操作,或需高效处理的文本文件 |
| 缓冲区限制 | 缓冲区可用于读取或写入,但不能同时进行两种操作 | 需明确读写方向的场景,如 “先读后写” 或 “纯读 / 纯写” 的文件处理 |
string path = @"C:\Users\Lenovo\Desktop\TestFile\wx-dy.mp4";
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\wx-dybybufferStream.mp4";
bytes = new byte[size];
using (fr = new FileStream(path, FileMode.Open, FileAccess.Read))
{
BufferedStream br = new BufferedStream(fr);
using (fw = new FileStream(pathto, FileMode.Create, FileAccess.Write))
{
BufferedStream bw = new BufferedStream(fw);
int count = br.Read(bytes, 0, size);
while (count > 0)
{
bw.Write(bytes, 0, count);
count = br.Read(bytes, 0, size);
}
bw.Close();
}
br.Close();
}
BinaryReader

string path = @"C:\Users\Lenovo\Desktop\TestFile\wx-dy.mp4";
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\wx-dybybinaryStream.mp4";
bytes = new byte[size];
fr = new FileStream(path, FileMode.Open, FileAccess.Read);
fw = new FileStream(pathto, FileMode.Create, FileAccess.Write);
using (BinaryReader br = new BinaryReader(fr))
{
using (BinaryWriter bw = new BinaryWriter(fw))
{
int count = br.Read(bytes, 0, size);
while (count > 0)
{
bw.Write(bytes, 0, count);
count = br.Read(bytes, 0, size);
}
}
}
fr.Close();
fw.Close();
private async void button6_ClickAsync(object sender, EventArgs e)
{
string path = @"C:\Users\Lenovo\Desktop\TestFile\wx-dy.mp4";
await ReadFileAsync02(path);
}
private async Task ReadFileAsync02(string pathFName)
{
string pathto = @"C:\Users\Lenovo\Desktop\TestFile\ToHere\wx-dybyAsync.mp4";
Console.WriteLine($"异步读:{Thread.CurrentThread.ManagedThreadId}");
bytes = new byte[size];
using (fr = new FileStream(pathFName, FileMode.Open, FileAccess.Read, FileShare.Read, size, true))
{
using (fw = new FileStream(pathto, FileMode.Append, FileAccess.Write, FileShare.None, size, true))
{
int count = 0;
count = await fr.ReadAsync(bytes, 0, bytes.Length);
while (count != 0)
{
await fw.WriteAsync(bytes, 0, count);
count = await fr.ReadAsync(bytes, 0, bytes.Length);
}
}
}
Console.WriteLine($"异步复制完成!");
}

浙公网安备 33010602011771号