c# - 从文件中高效读取结构化二进制数据

标签 c# optimization binaryfiles

我有以下代码片段,用于读取二进制文件并验证它:

 FileStream f = File.OpenRead("File.bin");
 MemoryStream memStream = new MemoryStream();
 memStream.SetLength(f.Length);
 f.Read(memStream.GetBuffer(), 0, (int)f.Length);
 f.Seek(0, SeekOrigin.Begin);
 var r = new BinaryReader(f);
 Single prevVal=0;
 do
 {
    r.ReadUInt32();
    var val = r.ReadSingle();
    if (prevVal!=0) {
       var diff = Math.Abs(val - prevVal) / prevVal;
       if (diff > 0.25)
          Console.WriteLine("Bad!");
    }
    prevVal = val;
 }
 while (f.Position < f.Length);

不幸的是,它运行速度非常慢,我正在寻求改进。在 C++ 中,我只需将文件读入字节数组,然后将该数组重新转换为结构数组:

struct S{
   int a;
   float b;
}

我该如何在 C# 中执行此操作?

最佳答案

定义一个struct (可能是 readonly struct ),具有与您的 C++ 代码完全相同的显式布局( [StructLayout(LayoutKind.Explicit)] ),然后是以下之一:

  1. 将文件作为内存映射文件打开,获取指向数据的指针;使用 unsafe原始指针上的代码,或使用 Unsafe.AsRef<YourStruct>关于数据,以及Unsafe.Add<>迭代
  2. 将文件作为内存映射文件打开,获取指向数据的指针; create a custom memory (您的 T )的指针,并迭代跨度
  3. 将文件打开为 byte[] ;创建 Span<byte>超过byte[] ,然后使用MemoryMarshal.Cast<,>创建 Span<YourType> ,并迭代它
  4. 将文件打开为 byte[] ;使用fixed固定byte*并得到一个指针;使用unsafe遍历指针的代码
  5. 涉及“管道”的东西 - a Pipe那是缓冲区,也许使用 StreamConnectionFileStream上用于填充管道,以及从管道中出列的工作循环;复杂性:缓冲区可能不连续,并且可能在不方便的地方分割;只要第一个跨度不是至少 8 个字节,就需要可解决的但微妙的代码

(或这些概念的某种组合)

其中任何一个都应该像您的 C++ 版本一样工作。第四个很简单,但对于非常大的数据,您可能更喜欢内存映射文件

关于c# - 从文件中高效读取结构化二进制数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59825404/

相关文章:

c# - "Object reference not set to an instance of an object"in PresentationFramework with Live Shaping

sql-server - 日期相关性的优化不会改变计划

javascript - 如何使用 CasperJS 通过自定义 POST 请求下载文件

iOS - Swift 是否与应用程序二进制文件或操作系统捆绑在一起

c# - 最小起订量并抛出 SqlException

c# - Windows RT 如何逐行读取文本文件?

c# - 使 ASP.NET Identity 2.0 电子邮件确认 token 适用于 WCF 和 MVC

optimization - 是什么让 Apple 的 PowerPC memcpy 如此之快?

language-agnostic - 使用 HashMap 将二叉树插入优化为 O(1) 以写入重树

java - 如何使用 java 将八位字节流读取为纯字符串/文本?