编组大端字节集合到一个结构,以拉出值 [英] Marshalling a big-endian byte collection into a struct in order to pull out values

查看:183
本文介绍了编组大端字节集合到一个结构,以拉出值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个关于<一个有见地的问题href="http://stackoverflow.com/questions/2871/reading-a-c-c-data-structure-in-c-from-a-byte-array">reading一个C / C ++数据结构在C#中的字节数组,但我不能得到code的工作为我的收藏大端(网络字节序)字节。 (编辑:请注意,我真正的结构已经不仅仅是一个字段)。有没有一种方法,以字节元帅到结构的大端版本,然后拉出值框架的字节顺序(即主机,通常是小端)?

(请注意,倒车字节数组的不可以工作 - 每个值的字节必须扭转,它不会给你同样的集合倒车所有字节)

这应该总结一下我在寻找什么(LE = LittleEndian,BE =大尾端):

 无效的主要()
{
    变种leBytes =新字节[] {1,2,0,2,0};
    变种beBytes =新字节[] {0,1,0,2};
    美孚fooLe = ByteArrayToStructure&LT;富&GT;(leBytes);
    美孚fooBe = ByteArrayToStructureBigEndian&LT;富&GT;(beBytes);
    Assert.AreEqual(fooLe,fooBe);
}

[StructLayout(LayoutKind.Explicit,大小= 4)]
公共结构美孚{
    [FieldOffset(0)]
    公共USHORT firstUshort;
    [FieldOffset(2)]
    公共USHORT secondUshort;
}

牛逼ByteArrayToStructure&LT; T&GT;(byte []的字节),其中T:结构
{
    的GCHandle手柄= GCHandle.Alloc(字节,GCHandleType.Pinned);
    牛逼的东西=(T)Marshal.PtrToStructure(handle.AddrOfPinnedObject()的typeof(T));
    handle.Free();
    返回的东西;
}

牛逼ByteArrayToStructureBigEndian&LT; T&GT;(byte []的字节),其中T:结构
{
    ???
}
 

其他有用的链接:

一个结构,走上尾数关注字节

更多的字节,字节顺序(字节顺序)

<一个href="http://www.builderau.com.au/architect/webservices/soa/Read-binary-files-more-efficiently-using-C-/0,339024590,320277904,00.htm">Read更有效地使用C#二进制文件

不安全,并从文件中读取

Mono的贡献问题

精通C#结构

解决方案

至于提到的在我的评论@ weismat的回答,有一个简单的方法来实现大端结构。它包括一个双逆转:原来字节被完全逆转,那么结构本身是原来的(大型)的数据格式的逆转

fooLe fooBe 主要将有相同的值对所有字段。 (通常情况下,小端struct和字节不会present,当然,但是这清楚地表明了字节顺序之间的关系。)

注:参见更新code 包括如何获得字节背出结构的

 公共无效的主要()
{
    VAR beBytes =新的字节[] {
        0x80的,
        0x80,0,
        0x80,0,
        0x80,0,0,0,
        0x80,0,0,0,
        0x80,0,0,0,0,0,0,0,
        0x80,0,0,0,0,0,0,0,
        0x3F的,0X80,0,0,1 //浮动(见http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness)
        0x3F的,0xF0,0,0,0,0,0,0,//双1
        0,0,0,0x67,0x6E,0x69,0x74,0x73,0x65,0x54 //测试\ 0 \ 0 \ 0
    };
    VAR leBytes =新的字节[] {
        0x80的,
        0,0x80,
        0,0x80,
        0,0,0,0x80,
        0,0,0,0x80,
        0,0,0,0,0,0,0,0x80,
        0,0,0,0,0,0,0,0x80,
        0,0,0x80,0x3F,1 //浮法
        0,0,0,0,0,0,0xF0,0x3F,//双1
        0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0,0,0 //测试\ 0 \ 0 \ 0
    };
    美孚fooLe = ByteArrayToStructure&LT;富&GT;(leBytes)使用.dump(LE);
    FooReversed fooBe = ByteArrayToStructure&LT; FooReversed&GT;(beBytes.Reverse()的ToArray())转储(是);
}

[StructLayout(LayoutKind.Sequential,包= 1)]
公共结构美孚{
    公众字节B1;
    公共短S;
    公共USHORT S;
    公众诠释我;
    公共UINT我;
    众长升;
    公共ULONG L,
    公众持股量F;
    公共双D;
    [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 10)]
    公共字符串MyString中;
}

[StructLayout(LayoutKind.Sequential,包= 1)]
公共结构FooReversed {
    [的MarshalAs(UnmanagedType.ByValTStr,SizeConst = 10)]
    公共字符串MyString中;
    公共双D;
    公众持股量F;
    公共ULONG L,
    众长升;
    公共UINT我;
    公众诠释我;
    公共USHORT S;
    公共短S;
    公众字节B1;
}

牛逼ByteArrayToStructure&LT; T&GT;(byte []的字节),其中T:结构
{
    的GCHandle手柄= GCHandle.Alloc(字节,GCHandleType.Pinned);
    牛逼的东西=(T)Marshal.PtrToStructure(handle.AddrOfPinnedObject()的typeof(T));
    handle.Free();
    返回的东西;
}
 

There is an insightful question about reading a C/C++ data structure in C# from a byte array, but I cannot get the code to work for my collection of big-endian (network byte order) bytes. (EDIT: Note that my real struct has more than just one field.) Is there a way to marshal the bytes into a big-endian version of the structure and then pull out the values in the endianness of the framework (that of the host, which is usually little-endian)?

(Note, reversing the array of bytes will not work - each value's bytes must be reversed, which does not give you the same collection as reversing all of the bytes.)

This should summarize what I'm looking for (LE=LittleEndian, BE=BigEndian):

void Main()
{
    var leBytes = new byte[] {1, 0, 2, 0};
    var beBytes = new byte[] {0, 1, 0, 2};
    Foo fooLe = ByteArrayToStructure<Foo>(leBytes);
    Foo fooBe = ByteArrayToStructureBigEndian<Foo>(beBytes);
    Assert.AreEqual(fooLe, fooBe);
}

[StructLayout(LayoutKind.Explicit, Size=4)]
public struct Foo  {
    [FieldOffset(0)] 
    public ushort firstUshort;
    [FieldOffset(2)] 
    public ushort secondUshort;
}

T ByteArrayToStructure<T>(byte[] bytes) where T: struct 
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(T));
    handle.Free();
    return stuff;
}

T ByteArrayToStructureBigEndian<T>(byte[] bytes) where T: struct 
{
    ???
}

Other helpful links:

Byte of a struct and onto endian concerns

A little more on bytes and endianness (byte order)

Read binary files more efficiently using C#

Unsafe and reading from files

Mono's contribution to the issue

Mastering C# structs

解决方案

As alluded to in my comment on @weismat's answer, there is an easy way to achieve big-endian structuring. It involves a double-reversal: the original bytes are reversed entirely, then the struct itself is the reversal of the original (big-endian) data format.

The fooLe and fooBe in Main will have the same values for all fields. (Normally, the little-endian struct and bytes wouldn't be present, of course, but this clearly shows the relationship between the byte orders.)

NOTE: See updated code including how to get bytes back out of the struct.

public void Main()
{
    var beBytes = new byte[] {
        0x80, 
        0x80,0, 
        0x80,0, 
        0x80,0,0,0, 
        0x80,0,0,0,
        0x80,0,0,0,0,0,0,0, 
        0x80,0,0,0,0,0,0,0, 
        0x3F,0X80,0,0, // float of 1 (see http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness)
        0x3F,0xF0,0,0,0,0,0,0, // double of 1
        0,0,0,0x67,0x6E,0x69,0x74,0x73,0x65,0x54 // Testing\0\0\0
    };
    var leBytes = new byte[] {
        0x80, 
        0,0x80,
        0,0x80, 
        0,0,0,0x80,
        0,0,0,0x80, 
        0,0,0,0,0,0,0,0x80, 
        0,0,0,0,0,0,0,0x80, 
        0,0,0x80,0x3F, // float of 1
        0,0,0,0,0,0,0xF0,0x3F, // double of 1
        0x54,0x65,0x73,0x74,0x69,0x6E,0x67,0,0,0 // Testing\0\0\0
    };
    Foo fooLe = ByteArrayToStructure<Foo>(leBytes).Dump("LE");
    FooReversed fooBe = ByteArrayToStructure<FooReversed>(beBytes.Reverse().ToArray()).Dump("BE");  
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Foo  {
    public byte b1;
    public short s;
    public ushort S;
    public int i;
    public uint I;
    public long l;
    public ulong L;
    public float f;
    public double d;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string MyString;
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct FooReversed  {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
    public string MyString;
    public double d;
    public float f;
    public ulong L;
    public long l;
    public uint I;
    public int i;
    public ushort S;
    public short s;
    public byte b1;
}

T ByteArrayToStructure<T>(byte[] bytes) where T: struct 
{
    GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
    T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(),typeof(T));
    handle.Free();
    return stuff;
}

这篇关于编组大端字节集合到一个结构,以拉出值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆