2015-11-16 96 views
1

有没有在C#中将普通字节数组转换为对象的方法?将字节数组转换为对象

e.g给出这个类:

class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 
} 

我想基本上能够做这样的事情:

var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; 
var obj = (Data)bytes; 
+0

你想实现什么?在你的字节和你想创建的实例之间的关系中必须有一些登录。 –

+2

从技术上讲,你可以实现一个*运算符*,即'public static explicit operator Data(Byte [] source){...}'但是* serialization *是更好的解决方案。 –

+1

得到一些想法 - [看到这里](http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html) – pedram

回答

5

你可以尝试编组:

声明类为顺序布局(请注意,您将需要使用Pack = 1):

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 
} 

元帅字节到数据类的新实例:

var bytes = new byte[] { 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0 }; 
GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
gcHandle.Free(); 

// Now data should contain the correct values. 

Console.WriteLine(data._int1); // Prints 1 
Console.WriteLine(data._int2); // Prints 2 
Console.WriteLine(data._short1); // Prints 3 
Console.WriteLine(data._long1); // Prints 4 

为了方便,你可以写上的数据的静态方法来进行转换:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 

    public static Data FromBytes(byte[] bytes) 
    { 
     GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
     gcHandle.Free(); 
     return data; 
    } 
} 

... 

var data = Data.FromBytes(new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0}); 

如果你真的想你可以写一个明确的操作员从字节数组转换,以获得语法在你的OP。我建议只使用Data.FromBytes()这将是一个更清晰的国际海事组织。

不过,只是为了完整性:

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
class Data 
{ 
    public int _int1; 
    public int _int2; 
    public short _short1; 
    public long _long1; 

    public static explicit operator Data(byte[] bytes) 
    { 
     GCHandle gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); 
     var data = (Data)Marshal.PtrToStructure(gcHandle.AddrOfPinnedObject(), typeof(Data)); 
     gcHandle.Free(); 
     return data; 
    } 
} 

... 

var data = (Data)new byte[] {1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 4, 0, 0, 0, 0, 0, 0, 0}; 
+0

@OguzOzgul完全不真实。 [你可以编组类或结构](https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute%28v=vs.71%29.aspx)。 –

+0

对不起,误认为不安全。改为upvote。 –

+0

谢谢,我想给我想要做的,这是最好的答案。 – Mark

1

使用BitConverter.ToInt32/Int16/Int64方法。你只需要指定起始索引,如:

Data data = new Data(); 
data._int1 = BitConverter.ToInt32(bytes, 0); 
data._int2 = BitConverter.ToInt32(bytes, 4); 
data._short1 = BitConverter.ToInt16(bytes, 8); 
data._long1 = BitConverter.ToInt64(bytes,10); 

只需记住:

BitConverter.ToInt32

数组中的字节的顺序必须反映 计算机系统的体系结构的字节顺序;

0

没有什么会一次性完成转换。

但是你可以建立在BitConverter顶部:

var d = new Data(); 
var sI32 = sizeof(Int32); 
d._int1 = BitConverter.ToInt32(bytes, 0); 
d._int2 = BitConverter.ToInt32(bytes, sI32); 
d._short1 = BitConverter.ToInt16(bytes, 2*sI32); 
… 
相关问题