C# 文件操作
IO基础概念
IO操作:文件/文件夹操作与读写。
文件夹:用来管理计算机文件的,每一个文件夹对应一块磁盘空间。它提供了指向对应空间的地址,它没有扩展名,也就不像文件的格式用扩展名来标识。
文件:一个具有符号的一组相关联元素的有序序列。文件可以包含范围非常广泛的内容。系统和用户都可以将具有一定独立功能的程序模块、一组数据或一组文字命名为一个文件,它具有永久存储。
流是一个字节序列,可用于对后备存储进行读取和写入操作,后备存储可以是多个存储媒介之一(例如,磁盘或内存)。
Stream 支持读取和写入字节。所有表示流的类都继承自Stream类。
流涉及三个基本操作:
(1)读取– 将数据从流传输到数据结构(如字节数组)中。
(2)写入– 将数据从数据源传输到流。
(3)查找– 对流中的当前位置进行查询和修改。
Path类
Path类:对包含文件/目录的路径信息的 System.String实例执行操作。
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
// 改变后缀名
string newPath = Path.ChangeExtension(path, "doc");
// 路径拼接
string path1 = @"E:\Biao\MyProjects";
string path2 = @"IOTest\1.txt";
string combinePath = Path.Combine(path1, path2);//path1 + path2;
// 获取扩展名
string ext = Path.GetExtension(combinePath);
// 获取文件名(带扩展名)
string fileName = Path.GetFileName(combinePath);
// 获取文件名(不带扩展名)
string fileNameNoExtention = Path.GetFileNameWithoutExtension(combinePath);
// 获取完整路径
string fullPath = Path.GetFullPath(combinePath);
// 是否有扩展名
bool isHasExtension = Path.HasExtension(combinePath);
目录操作 Directory/DirectoryInfo
Directory:用于通过目录和子目录进行创建、移动、删除、枚举的静态方法。
Directorylnfo: 用于创建、移动、删除、枚举目录和子目录的实例方法。
Directory 操作
string path = @"E:\Biao\MyProjects\IOTest\mu_1";
string path2 = @"E:\Biao\MyProjects\IOTest\mu_2";
//创建目录、判断目录是否存在
if (!Directory.Exists(path)) {
Directory.CreateDirectory(path);
}
// 删除目录 第二个参数为true的话:可以删除path的子目录;如果为false的话,path必须为空目录才能删除,否则会抛异常
Directory.Delete(path, true);
// 移动目录(包括子目录)注意要目标目录要加 目录/文件名
Directory.Move(path, path2 + @"\mu_1");
// 获取子目录、文件
string[] sonDirectories = Directory.GetDirectories(path);
string[] sonFiles = Directory.GetFiles(path);
DirectoryInfo 操作
/// <summary>
/// 递归遍历 某个目录下的所有子目录和文件
/// </summary>
/// <param name="path"></param>
/// <param name="result"></param>
private void GetAllDirectoriesAndFiles(string path, List<string> result) {
// 创建实例对象
DirectoryInfo directoryInfo = new DirectoryInfo(path);
// 获取对象的所有目录和文件
DirectoryInfo[] directories = directoryInfo.GetDirectories();
FileInfo[] files = directoryInfo.GetFiles();
// 把所有文件添加到result这个链表中
result.AddRange(files.Select(f => f.FullName));
// 依次遍历子目录
foreach(DirectoryInfo directory in directories) {
// 将该子目录添加到result这个链表中
result.Add(directory.FullName);
// 让子目录递归调用此方法(递归重复)
GetAllDirectoriesAndFiles(directory.FullName, result);
}
}
文件操作 File/FileInfo
File:提供用于创建、复制、删除、移动和打开文件的静态方法,并协助创建FileStream对象。
FileInfo:提供用于创建、复制、删除、移动和打开文件的实例方法,并协助创建FileStream对象。
FileMode 打开文件的方式 Create CreateNew Append Open OpenOrCreate
FileAccess 文件访问权限 Read Write ReadWrite
FileMode 创建、删除、复制、移动、追加文本
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
/// 以下将以2种方式实现(File/FileInfo)
/// 创建文件
if (!File.Exists(path)) {
File.Create(path);
//File.Create(path, 1024);//缓冲区大小
//StreamWriter sw= File.CreateText(path);
}
FileInfo fi = new FileInfo(path);
fi.Create();
//StreamWriter sw = fi.CreateText();
/// 删除文件
File.Delete(path);
FileInfo fi = new FileInfo(path);
fi.Delete();
/// 复制文件 源文件path内容不能为空
File.Copy(path, path2);
//File.Copy(path, path2, true);// 遇到同名文件,是否覆盖
FileInfo fi = new FileInfo(path);
fi.CopyTo(path2);
//fi.CopyTo(path2, true);
/// 移动文件
File.Move(path, path2);
//File.Move(path, path2,true);
FileInfo fi = new FileInfo(path);
fi.MoveTo(path2);
//fi.MoveTo(path2,true);
/// 追加文本
//StreamWriter sw = File.AppendText(path);
File.AppendAllText(path, "你好");
//List<string> list = new List<string>();
//list.Add("追加第1行");
//list.Add("追加第2行");
//list.Add("追加第3行");
//File.AppendAllLines(path, list);
FileInfo fi = new FileInfo(path);
StreamWriter sw = fi.AppendText();
FileAccess 打开、读取、写入
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
//文件打开、读写
/// 文件打开
File.Open(path, FileMode.Open);
//File.Open(path, FileMode.Create);
//File.Open(path, FileMode.Create,FileAccess.ReadWrite);
//File.OpenRead(path);// 只读
//File.OpenWrite(path);// 只写
//File.OpenText(path);// 打开文本文件
FileInfo fi= new FileInfo(path);
fi.Open(FileMode.Open);
//fi.Open(FileMode.CreateNew, FileAccess.Read);
//fi.OpenWrite();
//fi.OpenRead();
//fi.OpenText();
/// 文件读取
File.ReadAllLines(path);
//File.ReadAllText(path);
//File.ReadAllBytes(path);//二进制文件
//File.ReadAllText(path);//文本文件
/// 文件写入
string[] strs = new string[10];
File.WriteAllLines(path, strs);
//string str = "11111111111";
//File.WriteAllText(path, str);
//byte[] bytes=new byte[10];
//File.WriteAllBytes(path,bytes);
流
Stream介绍
Stream:提供字节序列的一般视图。这是一个抽象类。它是所有流的抽象基类
提供了以字节的形式从流中读取内容
【字符流】StreamReader和StreamWriter类帮我们实现在流上读写字符流的功能
常用的Stream的子类有:【字节流】
1)MemoryStream 存储在内存中的字节流
2)FileStream 存储在文件系统的字节流
3)BuferedStream 为其他流提供缓冲的流
一个汉字字符占2个字节;一个字节占8位。
StreamReader 读取【字符流】
StreamReader派生于TextReader,以下关于TextReader介绍。
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
/// StreamReader读取
TextReader reader = new StreamReader(path);
//StreamReader reader = new StreamReader(path);
// 方式1:一行一行读
string s= reader.ReadLine();
while (s != null) {
Console.WriteLine(s);
s = reader.ReadLine();
}
// 方式2:从头到尾
//string s = reader.ReadToEnd();
//Console.WriteLine(s);
// 方式3:读取下一个字符,不是读取次字符
reader.Read();// 读完之后,更改到下一个字符位置
reader.Peek();// 读完之后,不更改状态
reader.Close();// 关闭
StreamWriter 写入【字符流】
StreamWriter派生于TextWriter,以下关于TextWriter介绍。
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
/// StreamWriter写入
TextWriter writer = new StreamWriter(path,true);//追加的方式写入
//TextWriter writer = new StreamWriter(path);
writer.Write(writer.NewLine);//新行
writer.WriteLine("追加第一句话!");
writer.Write("追加第二句话!");
writer.WriteLine(33333);
writer.Flush();//如果不加这句,writer写入的内容将在Close()之后写进文件;加上这句,将在执行这句话后,直接写入了文件。
writer.WriteLine("追加第4句话");
writer.Close();
writer.Dispose();//释放
FileStream 【字节流】
FileStream介绍
FileStream对文件系统中的文件进行读取、写入、打开和关闭,使用Read、Write、CopyTo和 Flush方法来执行同步操作,或使用ReadAsync、WriteAsync、CopyToAsync和l FlushAsync方法执行异步操作。
使用异步方法来执行占用大量资源的文件操作,而不会阻止主线程。
构造函数:
FileStream(String,FileMode):
FileStream(String,FileMode,FileAccess)
FileStream(String, FileMode, FileAccess, FileShare)
FileStream(String, FileMode, FileAccess,FileShare, Int32)
第一个参数是文件路径;第二个参数是文件模式,表示以何种方式打开或创建文件;
第三个是文件的访问方式;第四个:文件的共享方式;第五个:缓冲区大小
FileStream使用
同步
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
byte[] data=new byte[1024];
using (FileStream fr=new FileStream(path, FileMode.OpenOrCreate,FileAccess.Read)) {
using(FileStream fw=new FileStream(path2, FileMode.OpenOrCreate, FileAccess.Write)) {
int count = 0;
do {
count=fr.Read(data, 0, data.Length);
fw.Write(data, 0, count);
}while(count!=0);
}
}
异步【对比同步】
private async void button6_Click(object sender, EventArgs e) {
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
// 异步复制
await FileStreamCopyFileAsync(path, path2);
}
private async Task FileStreamCopyFileAsync(string sourcePath,string targetPath) {
byte[] data = new byte[1024];
using (FileStream fr = new FileStream(sourcePath, FileMode.OpenOrCreate, FileAccess.Read)) {
using (FileStream fw = new FileStream(targetPath, FileMode.OpenOrCreate, FileAccess.Write)) {
int count = 0;
do {
count = await fr.ReadAsync(data, 0, data.Length);
fw.Write(data, 0, count);
} while (count != 0);
}
}
}
MemoryStream 内存流【字节流】
MemoryStream介绍
MemoryStream 创建一个流,其后备存储为内存。
内存流 数据以无符号字节数组的形式保存在内存中,系统可以直接访问这些封装的数据而不必读取磁盘文件。更加贴近底层数据,读取的效率更高(读取速度更快,和文件流的主要区别),内存流可以降低系统对临时缓冲区和临时文件的需要。
因此我们编程中常常用内存流作为中转,与其他流进行数据交换。(如利用MemoryStream操作文件,然后传给FileStream中)
内存流到文件流的转换:将数据写入内存流,再转给文件流,再写入文件
MemoryStream使用
private void button7_Click(object sender, EventArgs e) {
//中转应用
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
byte[] data = new byte[1024];
// 开启一个内存流ms
MemoryStream ms= new MemoryStream();
// 将fr从文件读取的缓存流写入到ms的内存流中
using(FileStream fr=new FileStream(path,FileMode.OpenOrCreate, FileAccess.Read)) {
int count = 0;
do {
count = fr.Read(data, 0, data.Length);
ms.Write(data, 0, count);
}while (count != 0);
}
// 将ms中的内存流写入到fw的缓存流中
using (FileStream fw = new FileStream(path2, FileMode.OpenOrCreate, FileAccess.Write)) {
ms.WriteTo(fw);
}
// ms关闭、释放
ms.Close();
ms.Dispose();
}
BufferedStream 缓冲流 [字节流]
BufferedStream介绍
缓冲流,给另一个流添加一个缓冲区,以进行读写操作。
BufferedStream比StreamReader和StreamWriter的效率更高,特别是对于大文件,对于txt文件StreamReader和StreamWriter来讲可以以一行一行的方式进行操作,但是对于其他类型的文件这种方式就显得无能为力了,
此时使用BufferedStream可以方便的实现,同样对于可以有一行一行进行操作的文件类型,使用BufferedStream也有更高的效率。
缓冲区是内存中用于缓存数据的字节块,缓冲数据能够减少对操作系统的调用次数,缓冲数据主要存储在缓冲区中。
缓冲区提高读写性能。
缓冲区可用于读取或写入,但不能同时使用这两种方法。
BufferedStream 用于在不需要缓冲区时防止缓冲区降低输入和输出速度。
BufferedStream使用
private void button8_Click(object sender, EventArgs e) {
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
byte[] data = new byte[1024];
FileStream fr = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
FileStream fw = new FileStream(path2, FileMode.OpenOrCreate, FileAccess.Write);
using(BufferedStream br = new BufferedStream(fr, 1024)) {
using(BufferedStream bw = new BufferedStream(fw, 1024)) {
int count = 0;
do {
count = fr.Read(data, 0, data.Length);
bw.Write(data, 0, count);
} while (count != 0);
}
}
}
BinaryReader与BinaryWriter 二进制文件的读写
BinaryReader与BinaryWriter介绍
BinaryReader与BinaryWriter使用
private void button9_Click(object sender, EventArgs e) {
string path = @"E:\Biao\MyProjects\IOTest\1.txt";
string path2 = @"E:\Biao\MyProjects\IOTest\2.txt";
FileStream fr = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Read);
BinaryReader br = new BinaryReader(fr);
FileStream fw = new FileStream(path2, FileMode.OpenOrCreate, FileAccess.Write);
BinaryWriter bw = new BinaryWriter(fw);
byte[] data = new byte[1024 * 1024];
int count = 0;
do {
count = br.Read(data, 0, data.Length);
bw.Write(data, 0, count);
} while (count != 0);
br.Close();
bw.Close();
}