FileStream相关知识分享
一、如何理解FIleStream
通过前3章的学些,相信大家对于Stream已经有一定的了解,但是又如何去理解FileStream呢?请看下图:
我们磁盘中的任何文件都是通过二进制数组组成,最为直观的就是记事本了,当我们新建一个记事本时,它的大小时0KB,我们每次输入一个数字或字母时,文件便会自动增大到4KB,可见,随着我们输入的内容越来越多,文件也会越来越大,同理,当我们删除文件内容时,文件也会相应的减小,对了,聪明的你肯定会问:谁将内容以怎样的形式放到文件中去了?
好问题,还记得第一章流的概念嘛?对了,真实世界的一群鱼可以通过河流往前往各个地方,FileStream也一样,byte可以通过FileStream进行传输,这样我们便能在计算机上对任何文件进行一系列操作了。
二、FileStream的重要性
FileStream顾名思义文件流,我们电脑上的文件都可以通过文件流进行操作,例如文件的复制、简介、粘贴、删除、本地文件上传、下载、等许多重要的功能都离不开文件流。所以文件流不仅在本机上非常重要,在如今的网络世界上也万万不能缺少的,想象一下我们开启虚拟机后,直接从本地复制一个文件到虚拟机上,时多么的方便,如果没有文件流,这个将难以想象。(大家别误解,文件流通过网络流将客户都安上传的文件传到服务器端接收,然后通过文件流进行处理,下载正好相反)
三、FileStream常用构造函数介绍
1、FileStream(SafeFileHandle safeFileHandle,FileAccess fileAccess)
非托管参数SafeFileHandle简单介绍
SafeFileHandle:是一个文件安全句柄,这样的解释可能大家一头雾水,别急,大家先不要去理睬这深邃的含义,只要知道这个类型是C#非托管资源,也就是说它能够调用非托管资源的方法,而且不属于C#回收机制,所以我们必须使用GC手动或其他方式(Finalize或Dispose方法)进行非托管资源的回收,所以SafeFileHandle是一个默默无闻的保镖,一直暗中保护FileStream和文件的安全,为了让大家更好的理解这个保镖,请看第一段代码:
1 static void Main(string[] args) 2 { 3 var rootPath = Environment.CurrentDirectory; 4 var fileName = Path.Combine(rootPath, "TextFile1.txt");//@"TextFile1.txt";5 FileStream fileStream = new FileStream(fileName, FileMode.OpenOrCreate); 6 Console.ReadLine(); 7 File.Delete(fileName); 8 Console.ReadKey(); 9 }
我们运行一下,结果报错了,我看看一下错误:
为什么会报错呢?其实程序被卡在了Console.ReadLine()这里,FileStream并没有被释放,系统不知道这个文件是否还有用,所以帮我们保护这个文件(那个非托管资源SafeFileHandle所使用的内存还被占用着)所以SafeFileHandle在内部保护了这个文件从而报出了这个异常,如果我们将流关闭后,这个问题就不存在了。
所以,我们又回到了一个老问题上面,我们每次使用完FileStream后都必须将他关闭并释放资源。
2、FileStream(string str,FileModel model)
string 参数表示文件所在的地址,FileMode是个枚举,表示确定如何打开或创建文件 。
FileModel枚举参数包含以下内容:
成员名称 | 说明 |
Append | 打开现有文件并查找到文件尾,或创建新文件。FileMode.Append 只能同 FileAccess.Write 一起使用。 |
Create | 指定操作系统应创建新文件。如果文件已存在,它将被改写。这要求 FileIOPermissionAccess.Write。 System.IO.FileMode.Create 等效于这样的请求:如果文件不存在,则使用 CreateNew;否则使用 Truncate。 |
CreateNew | 指定操作系统应创建新文件。此操作需要 FileIOPermissionAccess.Write。如果文件已存在,则将引发 IOException。 |
Open | 指定操作系统应打开现有文件。打开文件的能力取决于 FileAccess 所指定的值。如果该文件不存在, 则引发 System.IO.FileNotFoundException。 |
OpenOrCreate | 指定操作系统应打开文件(如果文件存在);否则,应创建新文件。如果用 FileAccess.Read 打开文件,则需要 FileIOPermissionAccess.Read。如果文件访问为 FileAccess.Write 或 FileAccess.ReadWrite,则需要 FileIOPermissionAccess.Write。如果文件访问为 FileAccess.Append,则需要 FileIOPermissionAccess.Append。 |
Truncate | 指定操作系统应打开现有文件。文件一旦打开,就将被截断为零字节大小。此操作需要 FileIOPermissionAccess.Write。 试图从使用 Truncate 打开的文件中进行读取将导致异常。 |
3、FileStream(IntPtr intPtr,FIleAccess fileAccess,Boolean ownsHandle)
FileAccess参数也是一个枚举,表示对该文件的操作权限:
参数ownsHandle:也就是类似于前面和大家介绍的SafeFileHandler,有2点必须注意:(1)对于指定的文件句柄,操作系统不允许所请求的access,例如:当access为Write或ReadWrite而文件句柄设置为只读访问的时候,会出现异常。所以ownsHandle才是老大,FileAccess的权限应该在ownsHandle的范围内。(2)FileStream假定它的句柄有独占控制权,当FileStream也持有句柄时,读取、写入或查找可能会导致数据破坏,为了数据安全,请使用句柄前调用Flush,并避免在使用完句柄后调用Close以外的任何方法。
4、FileStream(string str,FileModel model,FileAccess,fileAccess,FileShare fileShare)
FileShare:同样时一个枚举类型,确定文件如何由进程共享。