使用bigEndian转换为字节数组

时间:2017-11-25 10:51:41

标签: c# marshalling data-conversion

嗨我试图找到如何将struct转换为字节数组(从小端到大)

我知道如何将struct转换为字节数组,但问题是如何通过从小端到大端的转换来实现。

struct中的数据是luttle endian,但由于Bus Standard,字节数组的数据必须是BigEndian ...

我找到了更多的转换解决方案,但对端序转换也没有太多。

对于struct到byteArray我使用:

    public byte[] getBytes<T>(T str)
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    } 

    public struct MyStruct
    {
        public UInt32 A1;
        public UInt16 A2;
        public Int16  A3;
        public Byte   B1;
    }

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用包含数组的结构的第一种方法?这不起作用,因为Marshal.SizeOf将返回指向int-array的指针的大小(x86 = 4,x64 = 8)而不是int数组的长度......

我不确定如何将数组写入C中的字节数组。但我认为以下内容:

new int[] { 10,11,12 }
应该产生一个12字节长的字节数组:每个数组项的长度为4个字节,四个字节为4个字节。因此,在小端系统上,它看起来像是 new byte[] { 3,0,0,0, 10,0,0,0, 11,0,0,0, 12,0,0,0 }
我也不知道如何看待大端系统,但我认为只有字节块必须反转而不是顺序。因此,它可以像一个大端系统 new byte[] { 0,0,0,3, 0,0,0,10, 0,0,0,11, 0,0,0,12 }
或者,如果物品的顺序也必须颠倒,它可能看起来像是 new byte[] { 0,0,0,3, 0,0,0,12, 0,0,0,11, 0,0,0,10 }

public static byte[] StructToArray<T>(T obj)
{
    var size = Marshal.SizeOf(obj);
    var mem = new MemoryStream(size);
    var fields = obj.GetType().GetFields();
    var little = BitConverter.IsLittleEndian;

    foreach(var field in fields)
    {
        var val = field.GetValue(obj);
        var type = val.GetType();

        if(type == typeof(int))
        {
            var raw = BitConverter.GetBytes((int)val);
            if (little) raw = raw.Reverse().ToArray();
            mem.Write(raw, 0, raw.Length);
        }
        else if(type == typeof(int[]))
        {
            var array = (int[])val;
            var length = BitConverter.GetBytes(array.Length);
            if (little) length = length.Reverse().ToArray();
            var raw = array.Select(x => BitConverter.GetBytes(x)).ToList();

            if (little) raw = raw.Select(x => x.Reverse().ToArray()).ToList();
            // Write the length...
            mem.Write(length, 0, length.Length);
            // ...and the items in "normal" order
            for (int i = 0; i < raw.Count; i++)
                mem.Write(raw[i], 0, raw[i].Length);                    
        }
    }
    return mem.ToArray();
}

另请注意,.GetFields()的{​​{3}}页面包含以下声明:

GetFields方法不会按特定顺序返回字段,例如按字母顺序或声明顺序。您的代码不得依赖于返回字段的顺序,因为该顺序会有所不同。

这就是为什么使用属性来定义订单而不依赖于您正在使用的框架版本以声明顺序返回它们的巧合。