在下面的示例 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)构造函数,它接受字节数组并使用 BinaryReader或 BitConverter从字节数组中读取的类(您必须将其包装在 BinaryReader
的 MemoryStream
中)或简单地将字节数组的部分转换为您需要的值( 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/