c# - 将字节数组复制到 C# 中类/结构中的各个字段

标签 c# byte bytearray memcpy

在下面的示例 C# 代码中,我有一个从套接字读取的字节数组。我想将数据解析为“exampleClass”的各个字段(前 8 个字节为 64 位变量“field1”,接下来的 4 个字节为 32 位变量“field2”,等等)

using System;
namespace CsByteCopy
{
  class Program
  {
    class ExampleClass
    {
      public UInt64 field1;
      public UInt32 field2;
      public UInt16 field3;
      public byte[] field4 = new byte[18];
    }

    static void Main(string[] args)
    {
      byte[] exampleData =
      {
        // These 8 bytes should go in 'field1'
        0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
        // These 4 bytes should go in 'field2'
        0x08,0x09,0x0A,0x0B,
        // These 2 bytes should go in 'field3'
        0x0C,0x0D,
        // These 18 * 1 bytes should go in 'field4'
        0x0E,0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
      };

      ExampleClass exampleClass = new ExampleClass();
      // Perform copy
    }
  }
}

自从我上次使用 C 以来已经有很长时间了,但如果我没记错的话,我可能已经能够通过一次 memcpy() 调用来填充类中的所有字段。 在 C# 中填充“exampleClass”字段的最有效方法是什么?

最佳答案

您有很多选择,最好的选择通常取决于您的程序需要/可以处理的内容以及您想要的速度。有很多文章解释了用数据填充类或结构的不同方法。

二进制序列化是一种方式。这需要您编写自定义序列化程序,这很容易。一个MSDN article regarding that表明它并不太难。

您可以编写一个私有(private)构造函数,它接受字节数组并使用 BinaryReaderBitConverter从字节数组中读取的类(您必须将其包装在 BinaryReaderMemoryStream 中)或简单地将字节数组的部分转换为您需要的值( BitConverter).在 BitConverter 的情况下,您还需要使用 Buffer.BlockCopy 将字节数组的剩余数据复制到您的类中的字节数组字段

第三种方法,通常也是最快的方法,是将您的类转换为结构并使用不安全代码将字节数组转换为该结构。像这样:

unsafe struct ExampleClass
{
   public ulong field1;
   public uint field2
   public ushort field3
   public fixed byte field4[18];

   public static ExampleClass ReadStruct(byte[] data)
   {
       fixed (byte* pb = &data[0])
       {
           return *(ExampleClass*)pb;
       }
   }
}

当然,上面的代码只有在可以使用不安全代码的情况下才有效。此外,将类转换为结构可能也不是您想要的。在大多数情况下,结构按值传递给函数,因此调用方法复制整个结构(在本例中为 32 字节)而不是传递引用(4 或 8 字节,取决于 CPU 架构)并且可以 降低程序的效率。按值传递的结构也有异常(exception),您可以使用自己喜欢的搜索引擎。

如果您不能使用不安全的代码,还有 Marshal.PtrToStructure 可以执行与上述代码相同的操作,但速度要慢大约 10 倍。您还需要使用 MarshalAs 属性来指定数组的大小,而不是使用 fixed 关键字(这是不安全的)。到那时,您不妨使用 BinaryReader/BitConverter,因为它会比 marshal 类更快。

关于c# - 将字节数组复制到 C# 中类/结构中的各个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7030150/

相关文章:

c# - 将 mm/dd/yyyy 转换为 JsonDate 格式

c# - 获取一些用于检测的 Windows Phone 属性

byte - 将十六进制位转换为字节

android - yuv.compressToJpeg 不接受 ByteArrayOutputStream?

jsf - 未调用 PrimeFaces fileDownload 方法?

c# - 设计窗口样式

c# - 如何在 ASP.net 中显示加载页面指示器?

Mysql根据前缀计算总内存

byte - 从 php.ini 中的速记字节表示法获取字节值

java - 如何将 Java 字节数组转换为 Scala 字节数组?