会写这篇纯属机缘巧合,虽然一直以来认为对单一文件的读、写操作是不冲突,可并行的,但实际并未实践过。正好有个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. “伏魔”赏金 | WebShell检测之「模拟污点引擎」首次公测,邀你来战!

    安全是一个动态的过程,攻防对抗如同在赛博世界里降妖伏魔,其要义是:取彼之长,补己之短.--伏魔引擎的诞生 伏魔引擎挑战赛 注册时间: 2022.01.10 00:00:00 - 2022.01.24 ...

  2. 《剑指offer》面试题16. 数值的整数次方

    问题描述 实现函数double Power(double base, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 示例 1: 输入: 2.0 ...

  3. CUDA 入门(转)

    CUDA(Compute Unified Device Architecture)的中文全称为计算统一设备架构.做图像视觉领域的同学多多少少都会接触到CUDA,毕竟要做性能速度优化,CUDA是个很重要 ...

  4. eclipse导入项目jdk版本不一样

    一:eclipse导入项目jdk版本不一样解决方案 参考博文: https://www.cnblogs.com/chenmingjun/p/8472885.html 选中项目右键 --> Pro ...

  5. 模拟axios的创建[ 实现调用axios()自身发送请求或调用属性的方法发送请求axios.request() ]

    1.axios 函数对象(可以作为函数使用去发送请求,也可以作为对象调用request方法发送请求) ❀ 一开始axios是一个函数,但是后续又给它添加上了一些属性[ 方法属性] ■ 举例子(axio ...

  6. unity3d inputfield标签控制台打印object

    inputfield标签控制台打印object 这说明没有字符串给入 这是因为 inputfield下的text不能人为写入值,只能在game界面输入. 所以这个标签里的text做个默认值不好搞.

  7. Allure测试报告完整学习笔记

    目录 简介 安装Allure Allure测试报告的结构 Java TestNG集成Allure Report Python Pytest集成Allure Report 简介 假如你想让测试报告变得漂 ...

  8. 为什么ConcurrentHashMap是线程安全的?

    ConcurrentHashMap 是 HashMap 的多线程版本,HashMap 在并发操作时会有各种问题,比如死循环问题.数据覆盖等问题.而这些问题,只要使用 ConcurrentHashMap ...

  9. 优化.NET 应用程序 CPU 和内存的11 个实践

    https://michaelscodingspot.com/cpu-bound-memory-bound/ 优化.NET 应用程序 CPU 和内存的11 个实践 凡事都有其限度,对吧?汽车只能开这么 ...

  10. python22day

    内容回顾 递归练习 sys os logging shutil 函数结束啦 今日内容 面向对象 楔子:做一个人狗大战的游戏 技能要有归属感,人是人,狗是狗,技能的函数要写在对应函数内部,闭包. 复杂的 ...