将任何对象转换为byte []

Ste*_* H. 125 .net c# byte object

我正在编写一个原型TCP连接,我在整理要发送的数据时遇到了一些麻烦.

目前,我只发送字符串,但将来我们希望能够发送任何对象.

目前代码非常简单,因为我认为所有内容都可以转换为字节数组:

void SendData(object headerObject, object bodyObject)
{
  byte[] header = (byte[])headerObject;  //strings at runtime, 
  byte[] body = (byte[])bodyObject;      //invalid cast exception

  // Unable to cast object of type 'System.String' to type 'System.Byte[]'.
  ...
}
Run Code Online (Sandbox Code Playgroud)

这当然很容易用a来解决

if( state.headerObject is System.String ){...}
Run Code Online (Sandbox Code Playgroud)

问题是,如果我这样做,我需要检查在运行时无法转换为byte []的每种类型的对象.

由于我不知道在运行时无法将每个对象强制转换为byte [],因此这不是一个选项.

如何将任何对象转换为C#.NET 4.0中的字节数组?

Dan*_*olo 179

使用BinaryFormatter:

byte[] ObjectToByteArray(object obj)
{
    if(obj == null)
        return null;
    BinaryFormatter bf = new BinaryFormatter();
    using (MemoryStream ms = new MemoryStream())
    {
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,obj所有属性/字段中的任何属性/字段obj(以及所有属性/字段的所有内容)都需要使用该Serializable属性进行标记,以便使用此属性成功进行序列化.

  • 将"MemoryStream"的使用包装在"using"块中可能是个好主意,因为它会急切地释放所使用的内部缓冲区. (21认同)
  • 小心你对另一方面的"任何"对象所做的事情,因为它可能不再有意义(例如,如果该对象是文件的句柄,或类似) (11认同)
  • 由于安全问题,避免使用 BinaryFormatter。更多详细信息请参见:https://learn.microsoft.com/it-it/dotnet/standard/serialization/binaryformatter-security-guide (3认同)
  • 不再推荐 BinaryFormatter。BinaryFormatter 类型是危险的,不建议用于数据处理。有关更多详细信息,请参阅 Microsoft 文档。https://aka.ms/binaryformatter *BinaryFormatter 类型很危险,不建议用于数据处理。应用程序应尽快停止使用 BinaryFormatter,即使它们认为正在处理的数据是值得信赖的。BinaryFormatter 不安全且无法使其安全。* (2认同)

kom*_*bsh 99

查看这篇文章:http://www.morgantechspace.com/2013/08/convert-object-to-byte-array-and-vice.html

使用以下代码

// Convert an object to a byte array
private byte[] ObjectToByteArray(Object obj)
{
    if(obj == null)
        return null;

    BinaryFormatter bf = new BinaryFormatter();
    MemoryStream ms = new MemoryStream();
    bf.Serialize(ms, obj);

    return ms.ToArray();
}

// Convert a byte array to an Object
private Object ByteArrayToObject(byte[] arrBytes)
{
    MemoryStream memStream = new MemoryStream();
    BinaryFormatter binForm = new BinaryFormatter();
    memStream.Write(arrBytes, 0, arrBytes.Length);
    memStream.Seek(0, SeekOrigin.Begin);
    Object obj = (Object) binForm.Deserialize(memStream);

    return obj;
}
Run Code Online (Sandbox Code Playgroud)

  • +1用于提供代码和解码方法. (17认同)
  • 正如[本回答](http://stackoverflow.com/a/4865123/1852105)的评论中提到的那样,`MemorySteam`应该包含在`using`块中. (9认同)

Abe*_*rro 26

像其他人之前所说的那样,你可以使用二进制序列化,但它可能产生额外的字节或被反序列化为具有不完全相同数据的对象.另一方面,使用反射非常复杂且非常慢.有另一个解决方案可以严格地将您的对象转换为字节,反之亦然 - 编组:

var size = Marshal.SizeOf(your_object);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(your_object, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
Run Code Online (Sandbox Code Playgroud)

并将字节转换为对象:

var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(bytes, 0, ptr, size);
var your_object = (YourType)Marshal.PtrToStructure(ptr, typeof(YourType));
Marshal.FreeHGlobal(ptr);
Run Code Online (Sandbox Code Playgroud)

对于小对象和结构,使用这种方法比较你自己的逐字段序列化(因为从/向非托管内存的双重复制),这明显更慢,部分不安全,但是这是将对象严格转换为byte []而不实现序列化的最简单方法没有[Serializable]属性.

  • 注意潜在用户虽然非常聪明,但这个答案不适用于结构数组,无法作为非托管结构编组的对象或者在其层次结构中具有ComVisible(false)父对象的对象. (2认同)

kir*_*ran 13

使用Encoding.UTF8.GetBytes比使用更快MemoryStream。在这里,我使用NewtonsoftJson将输入对象转换为 JSON 字符串,然后从 JSON 字符串中获取字节。

byte[] SerializeObject(object value) =>Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(value));
Run Code Online (Sandbox Code Playgroud)

@Daniel DiPaolo 版本的基准测试

Method                    |     Mean |     Error |    StdDev |   Median |  Gen 0 | Allocated |
--------------------------|----------|-----------|-----------|----------|--------|-----------| 
ObjectToByteArray         | 4.983 us | 0.1183 us | 0.2622 us | 4.887 us | 0.9460 |    3.9 KB |
ObjectToByteArrayWithJson | 1.548 us | 0.0309 us | 0.0690 us | 1.528 us | 0.3090 |   1.27 KB |
Run Code Online (Sandbox Code Playgroud)


Jar*_*Par 12

您正在寻找的是序列化..Net平台有几种可用的序列化形式


Fra*_*Thu 8

public static class SerializerDeserializerExtensions
{
    public static byte[] Serializer(this object _object)
    {   
        byte[] bytes;
        using (var _MemoryStream = new MemoryStream())
        {
            IFormatter _BinaryFormatter = new BinaryFormatter();
            _BinaryFormatter.Serialize(_MemoryStream, _object);
            bytes = _MemoryStream.ToArray();
        }
        return bytes;
    }

    public static T Deserializer<T>(this byte[] _byteArray)
    {   
        T ReturnValue;
        using (var _MemoryStream = new MemoryStream(_byteArray))
        {
            IFormatter _BinaryFormatter = new BinaryFormatter();
            ReturnValue = (T)_BinaryFormatter.Deserialize(_MemoryStream);    
        }
        return ReturnValue;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以像下面的代码一样使用它.

DataTable _DataTable = new DataTable();
_DataTable.Columns.Add(new DataColumn("Col1"));
_DataTable.Columns.Add(new DataColumn("Col2"));
_DataTable.Columns.Add(new DataColumn("Col3"));

for (int i = 0; i < 10; i++) {
    DataRow _DataRow = _DataTable.NewRow();
    _DataRow["Col1"] = (i + 1) + "Column 1";
    _DataRow["Col2"] = (i + 1) + "Column 2";
    _DataRow["Col3"] = (i + 1) + "Column 3";
    _DataTable.Rows.Add(_DataRow);
}

byte[] ByteArrayTest =  _DataTable.Serializer();
DataTable dt = ByteArrayTest.Deserializer<DataTable>();
Run Code Online (Sandbox Code Playgroud)