佳佳的博客
Menu
首页
《.NET Core 实战》 [No.263~264] 内存映射文件
Posted by
佳佳
on 2020-03-26
IT
C#
.NET Core
《.NET Core 实战》
读书笔记
<!-- # 《.NET Core 实战》 [No.263~264] 内存映射文件 --> <!-- dotnet-core-memory-mapped-file --> 内存映射文件(`MemoryMappedFile`),其实是在应用程序内存空间中划分的一块特殊内存,可以像操作磁盘文件那样,在内存中新建文件,并写入或读取内容。 内存映射文件可以用于在**进程**之间共享数据。下面的两段代码处于两个不同的项目中,分别用于写入和读取内存映射文件。 ```csharp MemoryMappedFile file = MemoryMappedFile.CreateNew("test", 200L); using (MemoryMappedViewStream mmvstream = file.CreateViewStream()) using (StreamWriter writer = new StreamWriter(mmvstream)) { writer.WriteLine("Hi. Welcome to my blog<www.liujiajia.me>."); } Console.WriteLine("文件已写入内存"); Thread.Sleep(TimeSpan.FromSeconds(10)); ``` ```csharp Console.WriteLine("等待读取文件"); Thread.Sleep(TimeSpan.FromSeconds(5)); using (MemoryMappedFile file = MemoryMappedFile.OpenExisting("test")) using (MemoryMappedViewStream vstream = file.CreateViewStream()) using (StreamReader reader = new StreamReader(vstream)) { string str = reader.ReadLine(); Console.WriteLine(str); } Console.WriteLine("按 Enter 键退出"); Console.ReadLine(); ``` 同时运行可以看到跨进程共享数据的效果。输出结果如下:   在内存中创建的文件,当引用该内存的最后一个进程退出时,内存中的数据也会被清理并由系统回收。 通过关联磁盘文件和内存映射文件,可以在内存映射文件被回收时,自动写入到磁盘文件。 ```csharp // 建立磁盘文件和内存文件之间的关联并写入四个数值 using (MemoryMappedFile file = MemoryMappedFile.CreateFromFile("demo.data", FileMode.OpenOrCreate, "demo", 100L)) using (MemoryMappedViewStream vstream = file.CreateViewStream()) using (BinaryWriter writer = new BinaryWriter(vstream)) { writer.Write(157); writer.Write(1.18f); writer.Write(1990L); writer.Write(8.16d); } // 从文件中依次读取这四个数值 using (FileStream stream = File.OpenRead("demo.data")) using (BinaryReader reader = new BinaryReader(stream)) { Console.WriteLine($"文件大小:{stream.Length}"); Console.WriteLine($"读到的 int 值:{reader.ReadInt32()}"); Console.WriteLine($"读到的 float 值:{reader.ReadSingle()}"); Console.WriteLine($"读到的 long 值:{reader.ReadInt64()}"); Console.WriteLine($"读到的 double 值:{reader.ReadDouble()}"); } ``` 内存映射文件还可以映射文件的 **一段** 数据,这个功能在读写大型文件时很有用。 下面的示例继续使用上面关联的磁盘文件,通过映射部分数据的方式来读取写入的第二和第三个数值。 ```csharp // 从文件中读取中间的两个数值 long offset = Marshal.SizeOf(typeof(int)); // 4 long length = Marshal.SizeOf(typeof(float)) + Marshal.SizeOf(typeof(long)); // 4 + 8 using (MemoryMappedFile file = MemoryMappedFile.CreateFromFile("demo.data", FileMode.Open, "demo-part")) using (MemoryMappedViewAccessor accessor = file.CreateViewAccessor(offset, length)) { Console.WriteLine($"读到的 float 值:{accessor.ReadSingle(0)}"); Console.WriteLine($"读到的 long 值:{accessor.ReadInt64(Marshal.SizeOf(typeof(float)))}"); // position = 4 } ``` 上面两段代码的运行结果如下:  <!-- 参考 --> [1]: https://docs.microsoft.com/zh-cn/dotnet/standard/io/memory-mapped-files (内存映射文件) --- > 购买本书 => [《.NET Core实战:手把手教你掌握380个精彩案例》][10] -- *周家安* 著 --- [10]:https://union-click.jd.com/jdc?e=&p=AyIGZRhaEwAQBFUZXBIyEgRSEl0QCxc3EUQDS10iXhBeGlcJDBkNXg9JHU4YDk5ER1xOGRNLGEEcVV8BXURFUFdfC0RVU1JRUy1OVxUBFQ5THlIQMm1AEkRdb11GZyNTK0BBZwYIbylWcHILWStaJQITBlYbXB0LFQJlK1sSMkBpja3tzaejG4Gx1MCKhTdUK1sRCxQBVxtTEQIQBlwrXBULIloNXwZBXUReEStrJQEiN2UbaxYyUGlUG1kUBhcGUBILQgUXDlMeUkBVRlUBS10XBkIABhkJRzIQBlQfUg%3D%3D (《.NET Core实战:手把手教你掌握380个精彩案例》)
版权声明:原创文章,未经允许不得转载。
https://www.liujiajia.me/2020/3/26/dotnet-core-memory-mapped-file
“Buy me a nongfu spring”
« 《.NET Core 实战》 [No.265~266] 命名管道
[Jenkins]在 Pipeline 中上传文件到 FTP »
Commented by
sammy
on 2020-12-09
回复
在linux上示例代码跑不起来,不支持named map.
昵称
*
电子邮箱
*
回复内容
*
(回复审核后才会显示)
提交
目录
AUTHOR
刘佳佳
江苏 - 苏州
软件工程师
sammy
on 2020-12-09 回复