简体   繁体   English

将字节数组转换为对象

[英]Convert byte array to object

Is there a way in C# to convert a plain byte array to an object? C# 中有没有办法将普通字节数组转换为对象?

eg given this class:例如给定这个类:

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

I want to basically be able to do something like this:我希望基本上能够做这样的事情:

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;

You could try marshalling:你可以尝试编组:

Declare the layout of your class as Sequential (and note that you will need to use Pack = 1 ):将类的布局声明为 Sequential(并注意您需要使用Pack = 1 ):

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

Marshal the bytes into a new instance of the Data class:将字节编组到 Data 类的新实例中:

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

For convenience you could write a static method on Data to do the conversion:为方便起见,您可以在 Data 上编写一个静态方法来进行转换:

[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});

If you really wanted to you could write an explicit operator to convert from an array of bytes, to get the syntax in your OP.如果您真的想要,您可以编写一个显式运算符来从字节数组进行转换,以获取 OP 中的语法。 I would suggest just using Data.FromBytes() which is going to be a lot clearer IMO.我建议只使用Data.FromBytes()这将是更清晰的 IMO。

Still, just for completeness:不过,只是为了完整性:

[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};

Use BitConverter.ToInt32/Int16/Int64 methods.使用BitConverter.ToInt32/Int16/Int64方法。 You have only have to specify the starting index like:您只需要指定起始索引,如:

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);

Just remember:只记得:

BitConverter.ToInt32 BitConverter.ToInt32

The order of bytes in the array must reflect the endianness of the computer system's architecture;数组中的字节顺序必须反映计算机系统架构的字节序;

There is nothing that will do the conversion in one go.没有什么可以一次性完成转换。

But you can build on top of BitConverter :但是您可以在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);
…

Here is a way to convert a byte array into an object.这是一种将字节数组转换为对象的方法。

var binaryFormatter = new BinaryFormatter();
using (var ms = new MemoryStream(bytes))
{
    object obj = binaryFormatter.Deserialize(ms);
    return (Data)obj;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM