C# 是不是有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组?
Posted
技术标签:
【中文标题】C# 是不是有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组?【英文标题】:Does C# have a way to write an object with int fields (byte, ushort, ulong, etc.) as a byte array?C# 是否有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组? 【发布时间】:2021-09-06 11:15:06 【问题描述】:我正在尝试将仅具有 int 字段(ushort、ulong、uint、int 等)的对象转换为一个字节数组,其中包含每个 int 作为一个字节,按照它在对象中出现的顺序。 例如,如果我有一个表单对象
obj = subobj: uint firstProp: 500, ushort secondProp: 12, byte lastProp: 5
那么我希望字节数组是
0, 0, 1, 244, 0, 12, 5
我尝试使用序列化创建这个字节数组(如this answer 中所述),但我注意到每个字节前后都有一堆东西。基于this website,我相信这代表了我不想要的数据库和文件。
我知道在 C++ 中我可以使用 reinterpret_cast<uint8_t*>(obj)
来获得所需的结果。在 C# 中是否有等效的方法来执行此操作?
【问题讨论】:
不幸的是Buffer.BlockCopy
不支持聚合类型,即使只包含原始成员并且应该是 blittable。如果您愿意使用 /unsafe
进行编译,您可以使用 Marshal.PtrToStructure
及其反函数。
我强烈建议您不要这样做,因为底层表示可能会在不同的架构上发生变化。您可以查看***.com/questions/3278827/… 和docs.microsoft.com/en-us/dotnet/standard/native-interop/… 以获取有关不安全编组功能的信息,但您需要使用/unsafe 进行编译,正如@BenVoigt 所说。这些功能仅适用于结构。更好的方法是为这种类型编写自己的序列化器方法,将 BinaryWriter 作为参数。
@StevePick:底层表示非常明确,p/invoke 已经依赖它。如果您对默认设置不满意,可以使用 StructLayout.Explicit
和 FieldOffsetAttribute
进行完全控制。
@BenVoigt 哦,酷,我想编译器/运行时没有任何不同的架构或实现,那么?我链接了关于自定义结构布局的文档,以表明在绝对必要的情况下可以完成这些事情,但我仍然更喜欢安全路线。不过,要写很多烦人的样板。
@StevePick:默认设计是为了能够匹配 C 中定义的类型,并以与 C 结构完全相同的方式在平台间变化。自然地,任何IntPtr
成员都会在平台之间改变大小,其他成员在任何地方都是相同的大小,但可能会改变对齐方式(因此内部填充)。但是,如果您的目标是平台之间的互操作性而不是原生 C 代码,只需在 StructLayoutAttribute 上设置 Pack=1
即可禁用特定于平台的对齐/填充。
【参考方案1】:
您可以尝试这样做:
foreach(int value in obj)
byte lsbOfLsb = (byte)value;
byte msbOfLsb = (byte)(value >> 8);
byte lsbOfMsb = (byte)(value >> 16);
byte msbOfMsb = (byte)(value >> 24);
显然这只是想法。 您应该使用 for 循环而不是 foreach 并将所有元素解析为 int 例如. 其他方法是使用
检查数据类型typeof(value) //op 1
// OR
if(value is int) //e.g.
然后根据需要转换为字节。
【讨论】:
以上是关于C# 是不是有办法将具有 int 字段(字节、ushort、ulong 等)的对象编写为字节数组?的主要内容,如果未能解决你的问题,请参考以下文章