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");得到的是文件列表字符串
image

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

获取指定目录的子目录,文件列表

image
image

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 显示
image
image

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);
}

image

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

image

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($"异步复制完成!");
}
posted @ 2025-10-29 16:50  TheSheep2023  阅读(1)  评论(0)    收藏  举报