是否有一种通用的方法将结构写入Big Endian格式的字节?

时间:2014-09-12 12:31:42

标签: c# generics struct endianness computer-architecture

我发现问题such as this one已经接近解决我的困境。但是,我还没有找到一种以通用方式解决这个问题的简洁方法。

我有一个项目有很多结构,将用于二进制数据传输。这些数据需要是Big Endian,当然,大多数.Net架构都是Little Endian。这意味着当我将结构转换为字节时,我的值的字节顺序会反转。

是否有一种相当直接的方法来强制我的结构包含Big Endian格式的数据,或者有没有办法将这些结构一般性地写入输出Big Endian数据的字节数组(和字节数组到结构体)?

以下是我已经完成的一些示例代码。

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct StructType_1
{
    short shortVal;
    ulong ulongVal;
    int intVal;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public unsafe struct StructType_2
{
    long longVal_1;
    long longVal_2;
    long longVal;
    int intVal;
}

...

public static class StructHelper
{
    //How can I change the following methods so that the struct data 
    //is converted to and from BigEndian data?
    public static byte[] StructToByteArray<T>(T structVal) where T : struct
    {
        int size = Marshal.SizeOf(structVal);
        byte[] arr = new byte[size];
        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(structVal, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    }

    public static T StructFromByteArray<T>(byte[] bytes) where T : struct
    {
        int sz = Marshal.SizeOf(typeof(T));
        IntPtr buff = Marshal.AllocHGlobal(sz);
        Marshal.Copy(bytes, 0, buff, sz);
        T ret = (T)Marshal.PtrToStructure(buff, typeof(T));
        Marshal.FreeHGlobal(buff);
        return ret;
    }
}

2 个答案:

答案 0 :(得分:1)

如果您不介意将每个字段读取并写入流(可能会影响性能),您可以使用Jon Skeet的EndianBinaryWriter:https://stackoverflow.com/a/1540269/106159

代码看起来像这样:

public unsafe struct StructType_2
{
    long longVal_1;
    long longVal_2;
    long longVal;
    int intVal;
}

using (MemoryStream memory = new MemoryStream())
{
    using (EndianBinaryWriter writer = new EndianBinaryWriter(EndianBitConverter.Big, stream))
    {
        writer.Write(longVal_1);
        writer.Write(longVal_2);
        writer.Write(longVal);
        writer.Write(intVal);
    }

    byte[] buffer = memory.ToArray();

    // Use buffer
}

您可以使用EndianBinaryReader向相反方向发送数据。

这当然有两个相当大的缺点:

  • 它编写代码来读写每个字段。
  • 根据性能要求,这样做可能太慢了。

另请查看此类似问题的答案:Marshalling a big-endian byte collection into a struct in order to pull out values

答案 1 :(得分:0)

鉴于显示转换uint的{​​{3}}示例,我怀疑不会。