会写这篇纯属机缘巧合,虽然一直以来认为对单一文件的读、写操作是不冲突,可并行的,但实际并未实践过。正好有个UWP的程序要并行读取由Desktop Extension创建的文本,需要有个原型程序来验证,那不妨点开最新的VS 2022,顺手试试新的语法糖。
首先我们明确本篇对文件的操作均通过FileStream类来实现,FileStream在.NET 6进行了完全的重写,提高了性能和可靠性。但是本篇提到的共享读写权限,在之前版本也是完全支持的。
本篇提到的同时读写功能依赖FileStream的这个构造函数:

public FileStream (string path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share);

接下来我们通过实际的代码来进行分析。创建第一个工程CreateWriteSharedFile,该工程为.NET 6的Console程序,用于新建和写入内容到名为TestFile.txt的文件中。

var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestFile.txt");
var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fileStream);
int cout = 0;
while (true)
{
for (var i = 0; i < 10; i++)
{
sw.WriteLine(cout++);
Console.WriteLine(cout);
}
sw.Flush();
await Task.Delay(1000);
}

没有命名空间,没有类名和Main函数,这是C# 10里的新语法糖——顶级语句。作为简化后的程序入口点,十分适合我们这样的简短示例程序,对初学者也更友好。

代码的内容也很好懂,就是每个1秒连续写入10个自增的数字。唯一值得留意的是FileShare.ReadWrite,这个枚举标识对应的是后续其他对该文件的请求,不管是该进程内还是另外进程,均给与ReadWrite的权限。

我们的第二个工程ReadSharedFile仅做读取的操作,所以上面CreateWriteSharedFile中的FileShare只给Read也可以。但是相反,ReadSharedFile因为要允许CreateWriteSharedFile来进行写操作,所以它必须给与FileShare.Write枚举。

var path =Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestFile.txt");
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read,FileShare.Write);
var reader = new StreamReader(fileStream); while (!reader.EndOfStream)
{
Console.WriteLine(reader.ReadLine());
await Task.Delay(1000);
}

上述代码是在ReadSharedFile工程中读取由CreateWirteSharedFile创建的TestFile.txt中的内容。想要测试的话,build成功后运行对应的exe文件即可。并行的读和写操作很好理解,也不会存在冲突或生成脏数据的问题。

但如果是同时进行写操作会怎么样呢?之前的FileShare.ReadWrite就是为接下来的测试准备的。我们创建第二个写文件的工程SecondWriteSharedFile,同样要注意除了设置Read以外,还要为CreateWriteSharedFile特别准备Write权限,才能实现两边同时写入该文件的要求。

var path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "TestFile.txt");
var fileStream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
StreamWriter sw = new StreamWriter(fileStream); while (true)
{
for (var i = 0; i < 10; i++)
{
sw.WriteLine("A".PadRight(i,'A'));
Console.WriteLine("A".PadRight(i, 'A'));
} sw.Flush();
await Task.Delay(1000);
}

非常不幸的是,SecondWriteSharedFile在默认情况下,同样会从文件的头部开始写入,这样就覆盖了先运行的CreateWriteSharedFile在同样位置写入的内容。所以在一般情况下,我们要避免并行的写操作,这样极容易互相覆盖产生脏数据。
本篇简单地讨论了使用FileShare枚举,通过FileStream并行的读写文件的一般场景。希望能够抛砖引玉,给各位大佬在实际生产场景中以微小的帮助。
示例代码:(因为GitHub经常打不开,我在gitee也同样放了一份)

https://github.com/manupstairs/FileReadWriteSample
https://gitee.com/manupstairs/FileReadWriteSample

以下链接,是MS Learn上Windows开发的入门课程,单个课程三十分钟到60分钟不等,想要补充基础知识的同学点这里:

开始使用 Visual Studio 开发 Windows 10 应用

开发 Windows 10 应用程序

编写首个 Windows 10 应用

创建 Windows 10 应用的用户界面 (UI)

增强 Windows 10 应用的用户界面

在 Windows 10 应用中实现数据绑定

.NET 6学习笔记(1)——通过FileStream实现不同进程对单一文件的同时读写的更多相关文章

  1. VSTO学习笔记(四)从SharePoint 2010中下载文件

    原文:VSTO学习笔记(四)从SharePoint 2010中下载文件 上一次我们开发了一个简单的64位COM加载项,虽然功能很简单,但是包括了开发一个64位COM加载项的大部分过程.本次我们来给CO ...

  2. Java学习笔记四---打包成双击可运行的jar文件

    写笔记四前的脑回路是这样的: 前面的学习笔记二,提到3个环境变量,其中java_home好理解,就是jdk安装路径:classpath指向类文件的搜索路径:path指向可执行程序的搜索路径.这里的类文 ...

  3. Java学习笔记4---打包成双击可运行的jar文件

    写笔记四前的脑回路是这样的: 前面的学习笔记二,提到3个环境变量,其中java_home好理解,就是jdk安装路径:classpath指向类文件的搜索路径:path指向可执行程序的搜索路径.这里的类文 ...

  4. node学习笔记1——配置node环境变量及执行node文件

    最近在学习node,今天说一下node的变量环境配置.虽然网上有说,最新版的已经不需要配置这个东东了,但是我的电脑还是得配置.闲话少扯,进入正题: 1.安装node,这步就略过了.就是下载 node, ...

  5. UNP学习笔记(第十三章 守护进程和inetd超级服务器)

    关于守护进程可以查看apue的笔记 http://www.cnblogs.com/runnyu/p/4645046.html daemon_init函数 下面给出名为daemon_init函数,通过调 ...

  6. linux初级学习笔记二:linux操作系统及常用命令,文件的创建与删除和命名规则,命令行展开以及linux中部分目录的作用!(视频序号:02_3)

    本节学习的命令:tree,mkdir,rmdir,touch,stat,rm 本节学习的技能:Linux中主要的目录作用以及特殊的目录文件: 文件的命名规则,命令行展开: 文件的创建与删除: Linu ...

  7. java学习笔记(2):获取文件名和自定义文件过滤器

    //自定义文件过滤器import java.io.File; import javax.swing.filechooser.*; public class JavaChooser extends Fi ...

  8. struts2视频学习笔记 15-17 (访问或添加request属性,文件上传)

    课时15 访问或添加request/session/application属性 1.简单说 page指当前页面.在一个jsp页面里有效 2.request 指从http请求到服务器处理结束,返回响应的 ...

  9. Android(java)学习笔记184:生成 4种 不同权限的文件

    1.首先我们编写一个生成 4种 不同权限的文件的程序案例: (1)首先是activity_main.xml文件: <RelativeLayout xmlns:android="http ...

随机推荐

  1. 阿里神器 Seata 实现 TCC模式 解决分布式事务,真香!

    今天这篇文章介绍一下Seata如何实现TCC事务模式,文章目录如下: 什么是TCC模式? TCC(Try Confirm Cancel)方案是一种应用层面侵入业务的两阶段提交.是目前最火的一种柔性事务 ...

  2. python技巧一行命令搞定局域网共享

    python超强玩法--一行命令搞定局域网共享 ​ 今天刷到python的一个新玩法,利用python自带的http服务,快速创建局域网共享服务,命令如下: python -m thhp.server ...

  3. golang反射reflect机制用法

    package main import ( "fmt" "reflect" ) type User struct { Id int Name string Ag ...

  4. HTTP-常用请求头

    HTTP-常用请求头 Accept:表示客户端可以接收的数据类型 Accpet-Language:表示客户端可以接收的语言类型 User-Agent:表示客户端浏览器的信息 Host:表示请求时的服务 ...

  5. Vue3.2中的setup语法糖,保证你看的明明白白!

    vue3.2 到底更新了什么? 根据原文内容的更新的内容主要有以下 5 块: 1.SSR:服务端渲染优化.@vue/server-renderer包加了一个ES模块创建, 与Node.js解耦,使在非 ...

  6. AWS 模拟题知识点总结!

    一 题库的地址 https://www.lleicloud.com/index.php/aws-certified-saa-c01-practice-questions-c6-01/ 二 总结的知识点 ...

  7. glibc-2.18升级

    1.下载文件下载地址:https://mirrors.tuna.tsinghua.edu.cn/gnu/glibc/glibc-2.18.tar.gz 2.安装部署解压tar -zxvf glibc- ...

  8. 使用gdi+实时绘制picturebox(画个叉)

    private void DrawReticle(System.Drawing.Point pt, int size)//画一个透明的前景图片上画十字 { Bitmap bmp = new Bitma ...

  9. iBooker AI+财务提升星球 2020.4 热门讨论

    比特币量化套利的心路历程(附python量化招聘)(分享自知- 如何选择一份好的工作? 你知道为什么大家都想去好公司吗? 不- #财务知识# 可转债套利 辉丰转债128012套利之三个知道- #财务知 ...

  10. JAVA多线程学习九-原子性操作类的应用

    当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量i=1,A线程更新i+1,B线程也更新i+1,经过两个线程操作之后可能i不等于3,而是等于2.因为A和B线程在更新变量i ...