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.ExplicitFieldOffsetAttribute 进行完全控制。 @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 等)的对象编写为字节数组?的主要内容,如果未能解决你的问题,请参考以下文章

C#将文本框输入转换为Int [重复]

在c#中对字节数组表示的Int32求和

在 C# 中将 int[] 转换为 byte[]

C# 将 int 转换为 2 个字节的数组

在 c# 中,隐式短到字节是不可能的,但在隐式 int 到短时没有问题。源值始终与目标范围一致

使用反射设置 C# 结构/类字段时是不是可以避免装箱?