FileShare文件读写锁解决“文件XXX正由另外一进程使用,所以该进程没法访问此文件”(转)

开发过程当中,咱们每每须要大量与文件交互,读文件,写文件已成屡见不鲜,本地运行完美,但一上到投产环境,每每会出现不少使人措手不及的意外,或开发中的烦恼,所以,我对普通的C#文件操做作了一次总结,问题大部分以下:html

 

 1:写入一些内容到某个文件中,在另外一个进程/线程/后续操做中要读取文件内容的时候报异常,提示 System.IO.IOException: 文件“XXX”正由另外一进程使用,所以该进程没法访问此文件。windows

 2:在对一个文件进行一些操做后(读/写),随后想追加依然报System.IO.IOException: 文件“XXX”正由另外一进程使用,所以该进程没法访问此文件。次问题与1类似。post

 3:对一个文件进行一些操做后,想删除文件,依然报System.IO.IOException: 文件“XXX”正由另外一进程使用,所以该进程没法访问此文件。url

看到这些,有经验的同窗应该就会说资源没被释放掉,但也存在以下可能性。咱们对文件的操做很是频繁,因此写了特定的操做类/组件来维护文件之间的操做,知道特定的时刻才结束,常见的如日志,随着程序的启动便开始写日志,直到程序关闭。但其中也存在咱们须要提供一个特殊的操做(读/写/删除)来操做文件,例如咱们须要提供一个日志查看器来查看当前日志或全部日志,这时,便无可避免的发生了以上的问题。spa

复制代码
static void WriteFile(FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
{
    Console.WriteLine("please input your content.");
    var content = Console.ReadLine();
    FileStream fs = new FileStream(FILEPATH, fileMode, fileAccess, fileShare);
    var buffer = Encoding.Default.GetBytes(content);
    fs.Write(buffer, 0, buffer.Length);
    fs.Flush();
}
复制代码

首先,我声明了一个写文件方法,并调用它,它将我输入的内容写入指定的文件当中。操作系统

WriteFile(FileMode.Create, FileAccess.Write, FileShare.Read);
Console.ReadKey();

 

 

 

可是,在写文件操做结束以后,我并无释放掉文件流的资源。因此,此时会对文件形成一个锁。我尝试在windows中删除它。线程

 

很明显我没法删除掉这个文件,接下来,我尝试读取它。日志

 

复制代码
static void ReadFile(FileAccess fileAccess, FileShare fileShare)
{
    FileStream fs = new FileStream(FILEPATH, FileMode.Open, fileAccess, fileShare);
    var buffer = new byte[fs.Length];
    fs.Position = 0;
    fs.Read(buffer, 0, buffer.Length);
    Console.WriteLine(Encoding.Default.GetString(buffer));
}
复制代码

 

我实现了一个读文件方法,并调用了它。code

WriteFile(FileMode.Create, FileAccess.Write, FileShare.Read);
ReadFile(FileAccess.Read, FileShare.Read);

 

一切都很简单,访问模式为只读,这样应该就不会与上面的写锁进行冲突!htm

 

可是,结果并不是咱们所预想的那样,为何会提示没法访问?回想一下,在前面,我用windows的记事本打开了这个文件,并无提示说文件被锁定,我也的确能访问,那为什么到了程序里就没法访问了呢?或许,咱们应该把重点放在FileModeFileAccessFileShare这三个枚举身上,说不定就是它们搞的鬼。

 

FileMode

MSDN上的解释是指定操做系统打开文件的方式,我想这个应该不须要解释了,你们平时用得比较多了。MSDN的表格也很好的阐述了各个枚举值的做用,我就不在解释了。

FileAccess

定义用于文件读取、写入或读取/写入访问权限的常数。

 

这个枚举也用得比较多了,描述也很通俗易懂,我也不便再解释了。^_^!

FileShare

相信这个枚举类型你们会比较陌生,甚至有同窗见都没见过(惭愧的是,我也是才认识它没多久),陌生归陌生,但它的做用力也是不可低估,只是.Net帮咱们把它封装得比较好,以致于咱们一度认为它不是什么重要角色。好吧,进入主题!

包含用于控制其余 FileStream 对象对同一文件能够具备的访问类型的常数。这句话是什么意思呢?说实话,我如今看句话仍是以为很纠结,相信不少同窗看到也是一头雾水,不要紧,咱们先跳过!

 

看它的成员描述,和FileAccess非常类似,那咱们就尝试着来揭开它暂时神秘的面纱吧!

FileShare.Read

从字面上的意思,咱们能够理解为首先打开一个文件以后(资源未释放),咱们能够再用只读的方式读取文件从而不会抛出文件没法访问的异常。利用刚才实现的方法,能够轻易的再完成这个实验:

 

WriteFile(FileMode.Create, FileAccess.Write, FileShare.Read);
ReadFile(FileAccess.Read, FileShare.Read);

这是什么回事?不是都设置成已读了吗?或许只能在读文件的时候才能设置为只读共享。咱们再尝试一下:
 

ReadFile(FileAccess.Read, FileShare.Read);
ReadFile(FileAccess.Read, FileShare.Read);

 

此次的确是能在第一次没释放资源时再读,那咱们再试试可否在设置只读共享后写文件:

ReadFile(FileAccess.Read, FileShare.Read);
WriteFile(FileMode.Create, FileAccess.Write, FileShare.Read);

 

 

首先正确的读出了文件的内容,但当我尝试写入一些内容的时候却又报错了。那么,根据以上的实验,就能够得知这个只读的共享只有是在连续读取文件才有效!

 

FileShare.Write

结合Read的经验,字面上的意思应该能够理解为,只有在写文件时设置共享方式为Write,随后才能继续写入文件,不然会抛出异常。这里比较好玩的时,设置Write以后,万能的Window记事本也打不开文件了。

 

 

FileShare.ReadWrite

有了以上的经验,从字面上理解,能够认为这个ReadWrite必定是结合了Read和Write的特性。那到底它有什么用呢?上面咱们知道,在读文件设置Read共享能继续读而不能写,在写文件时设置Write共享则能继续写而不能读,可是当咱们设置了写共享后并想读取文件时怎么办?只能先释放资源再从新加载了吗?不须要,ReadWrite就是为此而生的。

 

WriteFile(FileMode.Create, FileAccess.Write, FileShare.Read);
ReadFile(FileAccess.Read, FileShare.ReadWrite);

 

不过这里写文件的时候并不容许把共享设置成Write,不然读文件时用ReadWrite则无效(报异常),但都设置为ReadWrite能够。这必定,即可以解决不少平常开发中的烦恼。

FileShare.None/FileShare.Delete

有了上面的经验,相信这两个你也很容易的就理解了,None则为不容许后续有任何操做,而Delete则是容许你随后进行删除操做。

原文连接FileShare枚举的使用(文件读写锁)

相关文章
相关标签/搜索