File与FileStream的比较
File根据官方解释是提供用于创建、复制、删除、移动和打开单一文件的静态方法, 并协助创建FileStream对象。
FileStream的官方解释是为文件提供Stream,既支持同步读写操作,也支持异步读写操作。
他们两个都处于using System.IO;
的命名空间下,查看源码File是一个静态类,所以使用时不需通过new创建新对象。而FileStream则需要通过new来创建新对象同时还要传入参数。
File使用方式较FileStream来说更加方便,但是方便的同时也就说明功能没有FileStream强大,不过处理一般的文件还是够用的。
代码示例
File的文件读写
/// 使用File进行文件读写操作
/// </summary>
/// <param name="path">源文件路径</param>
public void FileRead(string path)
{
//使用ReadAllLines读取,字符串数组接收
string[] strs= File.ReadAllLines(path);
foreach(string str in strs)
{
Console.WriteLine(str);
}
Console.WriteLine("============================================");
//使用ReadAllBytes以字节方式读取(可以读取计算机上任意文件),接收为字节数组
byte[] buffer = File.ReadAllBytes(path);
Console.WriteLine(Encoding.UTF8.GetString(buffer));
//在指定路径下创建文件,然后写入
File.WriteAllBytes(@"F:\testFile——副本.txt",buffer);
Console.WriteLine("============================================");
//使用ReadAllText,(只能读取文本文件)
Console.WriteLine(File.ReadAllText(path));
}
File的文件读写运行结果
文件用三种方式读取文件的输出。(如果你的是乱码你要看看你的编码是不是有问题,这里我统一使用utf8演示)
看得出来File.WriteAllBytes(@"F:\testFile——副本.txt",buffer);
也执行成功了。
FileStream文件读写
/// <summary>
/// 使用FileStream进行文件读取,可以指定缓存区大小,读取多少字节。
/// </summary>
/// <param name="path"></param>
public void FileStreamRead(string path)
{
using (FileStream fileReader = new FileStream(path, FileMode.Open, FileAccess.Read))//使用using开启1个流
{
byte[] buffer = new byte[1024];//向内存中申请1024字节=1KB的缓存;
int count = fileReader.Read(buffer, 0, buffer.Length);//读取1KB的字节到缓存中,返回值记录了实际写入了多少长度的字节。
Console.WriteLine(Encoding.UTF8.GetString(buffer));//
/*while (true)//进行循环读取和写入,从而读取全部文件。
{
int count = fileReader.Read(buffer, 0, buffer.Length);//读取1KB的字节到缓存中,返回值记录了实际写入了多少长度的字节。,返回值记录了实际写入了多少长度的字节。
if (count == 0)//如果返回缓存区实际写入了0字节则退出循环
{
Console.WriteLine("读取完毕!");
return;
}
else
{
Console.WriteLine(Encoding.UTF8.GetString(buffer,0,count));
}
}*/
}
}
FileStream文件读写运行结果
只读取1KB的内容,可以从图中看出并未读取完。为什么他们后面会是个“?”,因为一个汉字占2个字节,可能读取到1024个字节时他们后面的那个汉字只读取了一个字节,所以才显示的“?”。
使用while循环读取全部内容,可以看出内容都读取完毕。
File与FileStream的使用场景
从上面示例中可以看出,
File
是一个文件操作的静态类,支持对文件的基本操作,包括创建,拷贝,移动,删除和打开一个文件。适用于小的文件。如果文件太大全部读取到内存中,电脑内存小的可能无法运行。FileStream
是一个文件流,我的理解他俩就好比是File类依托于Filestream来处理的文件。FileStream可以以二进制的方式读取任何文件,包括视频、音频等,他也可以通过缓冲区来读取大文件。
可能我上面用的FileStream
来读取一个中文的文本文件不太恰当,因为会出现“?”的乱码。我想表达的就是,你可以通过设置缓存区来避免内存空间不够的问题。如下图,如果是一个4G的视频文件你用File.ReadAllBytes
一下读入到内存中操作肯定是不行的。这时候就要用到缓存区。
下面是一个复制音频文件(大小22.2MB)的示例
/// <summary>
/// 将一个文件以二进制读取,然后写入到指定文件中。从而实现文件以二进制流的形式复制。
/// </summary>
/// <param name="path1">源文件路径</param>
/// <param name="path2">目标文件路径</param>
public void FileCopy(string path1,string path2)
{
//使用using开启两个流
using (FileStream fileReader = new FileStream(path1, FileMode.Open, FileAccess.Read))//读取流
using (FileStream fileWriter = new FileStream(path2, FileMode.OpenOrCreate, FileAccess.Write))//写入流
{
byte[] buffer = new byte[1021 * 1024 * 5];//向内存中申请5MB的缓存;
while (true)//进行循环读取和写入,从而读取全部文件。
{
int count = fileReader.Read(buffer, 0, buffer.Length);//0是buffer的起始索引,buffer.Length是读取文件字节长度,读取5MB的字节到缓存中,返回值记录了实际写入了多少长度的字节。
if (count == 0)//如果返回缓存区实际写入了0字节则退出循环
{
Console.WriteLine("复制完毕!");
break;
}
else
{
fileWriter.Write(buffer, 0, count);//从缓存区里面读取实际写入的字节,然后写入对应目标文件。
}
}
}
}
最后
C#为文件操作提供了比较全面的类,上面的仅是我用过的一部分,还有许多对应不同情况特别方便的方法,比如只操作文本的话有StreamReader/StreamWriter,可以自己写代码的时候使用.
后多多看下不同方法的解释,试着使用下看看啥效果。我们总是在不断摸索中进步。
--------------------------------------------------------------
----------2020.6.1 🌤 六·一快乐!