asp.net 细说文件读写操作(读写锁)

 更新时间:2021年9月22日 10:19  点击:2035
问题大部分如下:

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

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

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

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

复制代码 代码如下:

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();

imageimage

但是,在写文件操作结束之后,我并没有释放掉文件流的资源。所以,此时会对文件造成一个锁。我尝试在windows中删除它。

image

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

复制代码 代码如下:

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));
}

我实现了一个读文件方法,并调用了它。
复制代码 代码如下:

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

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

image

但是,结果并非我们所预想的那样,为什么会提示无法访问?回想一下,在前面,我用windows的记事本打开了这个文件,并没有提示说文件被锁定,我也的确能访问,那为何到了程序里就无法访问了呢?或许,我们应该把重点放在FileMode,FileAccess,FileShare这三个枚举身上,说不定就是它们搞的鬼。
FileMode
MSDN上的解释是指定操作系统打开文件的方式,我想这个应该不需要解释了,大家平时用得比较多了。MSDN的表格也很好的阐述了各个枚举值的作用,我就不在解释了。

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

image

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

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

包含用于控制其他 FileStream 对象对同一文件可以具有的访问类型的常数。这句话是什么意思呢?说实话,我现在看句话还是觉得很纠结,相信很多同学看到也是一头雾水,没关系,我们先跳过!

image
看它的成员描述,和FileAccess很是相似,那我们就尝试着来揭开它暂时神秘的面纱吧!
FileShare.Read
从字面上的意思,我们可以理解为首先打开一个文件之后(资源未释放),我们可以再用只读的方式读取文件从而不会抛出文件无法访问的异常。利用刚才实现的方法,可以轻易的再完成这个实验:

复制代码 代码如下:

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

image

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

复制代码 代码如下:

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

image

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

复制代码 代码如下:

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

image

首先正确的读出了文件的内容,但当我尝试写入一些内容的时候却又报错了。那么,根据以上的实验,就可以得知这个只读的共享只有是在连续读取文件才有效!
FileShare.Write
结合Read的经验,字面上的意思应该可以理解为,只有在写文件时设置共享方式为Write,随后才能继续写入文件,否则会抛出异常。这里比较好玩的时,设置Write之后,万能的Window记事本也打不开文件了。

image

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

复制代码 代码如下:

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

image

不过这里写文件的时候并不允许把共享设置成Write,否则读文件时用ReadWrite则无效(报异常),但都设置为ReadWrite可以。这一定,便可以解决很多日常开发中的烦恼。
FileShare.None/FileShare.Delete
有了上面的经验,相信这两个你也很容易的就理解了,None则为不允许后续有任何操作,而Delete则是允许你随后进行删除操作。

黑箱子里的内容
对于文件操作,我们平常使用的比较多的可能是以下几种:

复制代码 代码如下:

File.AppendAllText("......");
File.AppendAllLines(...);
File.AppendText(...);
FileStream fs = new FileStream(path, FileAccess.Write);
fs.Write(....);

实际上它们也是在内部初始化了FileMode/FileAccess/FileShare,例如File的静态方法最后都会生成一个Stream实例,其中便调用了私有方法

image

尾声
现在,我们明白了,其实/FileShare就是控制文件流的“访问权限”,当然,这仅仅是入门的文件操作,自己做了笔记,也希望能给大家带来帮助,高级篇园子里已经有不少前辈写了文件读写锁方面的文章,感兴趣的同学可有搜索一下,前去观摩!!
作者:空逸云

[!--infotagslink--]

相关文章

  • R语言开发之CSV文件的读写操作实现

    这篇文章主要介绍了R语言开发之CSV文件的读写操作实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-05-06
  • FtpHelper实现ftp服务器文件读写操作(C#)

    这篇文章主要为大家详细介绍了FtpHelper实现ftp服务器文件读写操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • C++文件读写代码分享

    本文给大家分享的是2个C++实现文件读写的代码,都非常的简单实用,有需要的小伙伴可以参考下。...2020-04-25
  • c#保存窗口位置大小操作类(序列化和文件读写功能)

    这篇文章主要介绍了c#保存窗口位置大小操作类,其实就是把序列化和文件读写合到一块,大家参考使用...2020-06-25
  • PHP中文件读写操作

    PHP中文件读写操作   PHP中提供了一系列的I/O函数,能简捷地实现我们所需要的功能,包括文件系统操作和目录操作(如“复制[copy]”)。下面给大家介绍的是基本...2016-11-25
  • 详解python中的异常和文件读写

    这篇文章主要介绍了python中的异常和文件读写的的相关资料,帮助大家更好的理解和使用python,感兴趣的朋友可以了解下...2021-01-03
  • c# 共享状态的文件读写实现代码

    开发中有时会遇到要对文件进行共享状态的读写操作,代码如下,需要的朋友可以参考下...2020-06-25
  • c#实现ini文件读写类分享

    c#实现ini文件读写类分享,大家参考使用吧...2020-06-25
  • C#控制台进行文件读写的方法

    这篇文章主要介绍了C#控制台进行文件读写的方法,涉及C#操作文件读写的相关技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • php文件读写操作实例代码

    本教程举了大量的关于如何利用php来操作文件,如有截取文件 读取文件内容 格式化输出文件内容 锁定文件函数 以写入方式打开文件 csv文件等操作。 */ $fp=fopen(...2016-11-25
  • Node.js Streams文件读写操作详解

    如果你在处理应用中 IO 相关的操作,你可以利用 Node.js 中的流(stream),这篇文章主要为大家详细介绍了Node.js Streams文件读写操作,感兴趣的小伙伴们可以参考一下...2016-07-06
  • asp.net 细说文件读写操作(读写锁)

    开发过程中,我们玩玩需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发中的烦恼,因此,我对普通的C#文件操作做了一次总结...2021-09-22
  • C语言中对文件最基本的读取和写入函数

    这篇文章主要介绍了C语言中对文件最基本的读取和写入函数,是C语言入门学习中的基础知识,需要的朋友可以参考下...2020-04-25
  • php文件读写操作

    本文章主要介绍了在php中的文章读取与写文件的操作,我们主要讲取三个函数file_get_contents,fwrite,file用法,然后简单说is_readable判断文件是否可写。 首先是一个...2016-11-25
  • 深入解读Python如何进行文件读写

    文件的作用 就是把一些存储存放起来,可以让程序下一次执行的时候直接使用,而不必重新制作一份,省时省力,本文将带你了解通过python如何进行文件的读写操作...2021-10-25
  • C#实现ini文件读写操作

    这篇文章主要为大家详细介绍了C#实现ini文件的读写操作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-06-25
  • Perl中的文件读写学习笔记

    这篇文章主要介绍了Perl中的文件读写学习笔记,本文讲解了打开、关闭文件、读文件、写文件、判断文件状态等内容,需要的朋友可以参考下...2020-06-29
  • Python打开文件、文件读写操作、with方式、文件常用函数实例分析

    这篇文章主要介绍了Python打开文件、文件读写操作、with方式、文件常用函数,结合实例形式分析了Python文件的打开、读写及常用文件操作函数使用技巧,需要的朋友可以参考下...2020-04-30
  • 详解C++文件读写操作

    这篇文章主要为大家详细介绍了C++文件读写操作,感兴趣的小伙伴们可以参考一下...2020-04-25
  • C#实现文本文件读写方法汇总

    本文给大家汇总介绍了C#实现文本文件读写的方法,十分的简单实用,有需要的小伙伴可以参考下。...2020-06-25