一、如何理解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:同样时一个枚举类型,确定文件如何由进程共享。