【问题标题】: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 及其反函数。
  • 我强烈建议您不要这样做,因为底层表示可能会在不同的架构上发生变化。您可以查看stackoverflow.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 即可禁用特定于平台的对齐/填充。

标签: c# arrays casting binary integer


【解决方案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. 

然后根据需要转换为字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2015-03-09
    • 2020-04-16
    • 2013-01-29
    • 2021-11-30
    相关资源
    最近更新 更多