编组大端字节集合到一个结构,以拉出值 [英] Marshalling a big-endian byte collection into a struct in order to pull out values
问题描述
有一个关于<一个有见地的问题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:结构
{
???
}
其他有用的链接:
更多的字节,字节顺序(字节顺序) 小P>
<一个href="http://www.builderau.com.au/architect/webservices/soa/Read-binary-files-more-efficiently-using-C-/0,339024590,320277904,00.htm">Read更有效地使用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#
Mono's contribution to the issue
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屋!