C# 将字节数组转换为对象
在C#中有没有办法将普通字节数组转换为对象 e、 g鉴于这一类别:C# 将字节数组转换为对象,c#,C#,在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 =
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;
使用方法。您只需指定起始索引,如下所示:
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);
记住:
数组中字节的顺序必须反映
计算机系统结构
使用方法。您只需指定起始索引,如下所示:
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);
记住:
数组中字节的顺序必须反映
计算机系统结构
没有什么可以一次性完成转换 但您可以在以下基础上进行构建:
没有什么可以一次性完成转换 但您可以在以下基础上进行构建:
您可以尝试编组: 将类的布局声明为顺序布局(请注意,您需要使用
Pack=1
):
将字节封送到数据类的新实例中:
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};
您可以尝试编组: 将类的布局声明为顺序布局(请注意,您需要使用
Pack=1
):
将字节封送到数据类的新实例中:
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};
下面是一种将字节数组转换为对象的方法
var binaryFormatter = new BinaryFormatter();
using (var ms = new MemoryStream(bytes))
{
object obj = binaryFormatter.Deserialize(ms);
return (Data)obj;
}
下面是一种将字节数组转换为对象的方法
var binaryFormatter = new BinaryFormatter();
using (var ms = new MemoryStream(bytes))
{
object obj = binaryFormatter.Deserialize(ms);
return (Data)obj;
}
你想要实现什么?在字节与要创建的实例之间的关系中必须有一些登录名。从技术上讲,您可以实现一个运算符,即
公共静态显式运算符数据(字节[]源){…}
但序列化是更好的解决方案。了解一些情况-看起来您正在尝试读取从某些C/C++结构编写的数据。是这样吗?谢谢你的评论,我知道我可以使用BitConverter分别转换每个成员,我不能反序列化,因为数据一开始不是序列化的,它只是原始数据。它可以用C++来做,只是说我知道这一块数据真的是这个结构,把它当作这样的,但是也许你不能在C语言中这么容易地做。你想要达到什么?在字节与要创建的实例之间的关系中必须有一些登录名。从技术上讲,您可以实现一个运算符,即公共静态显式运算符数据(字节[]源){…}
但序列化是更好的解决方案。了解一些情况-看起来您正在尝试读取从某些C/C++结构编写的数据。是这样吗?谢谢你的评论,我知道我可以使用BitConverter分别转换每个成员,我不能反序列化,因为数据一开始不是序列化的,它只是原始数据。它可以在C++中完成,只是说我知道这一块数据是真的这个结构,把它当作这样,但是你可能不能在C很容易做到这一点。@ OguzOzgul完全不真实。谢谢,我想这是最好的答案。关于使用big-endian的系统呢?@Geograph你必须确保字节是正确的。(OP是在与C++的相同效果之后)。谢谢,我想这是最好的答案。关于使用big-endian的系统呢?@Geograph你必须确保字节是正确的。(OP是在与C++ CAST相同的效果之后)。