如何将字节数组转换为任何类型

26

大家好,我看到有人问如何将字节数组转换为intstringStream等类型的问题。答案都不尽相同,我个人也没有找到令人满意的答案。

下面是一些我们想要将字节数组转换为的类型:

UnityEngine.Font可以接受ttf数据。

UnityEngine.Testure2D可以接受来自像.png.jpg等图像文件的数据。

我们如何将字节数组转换为StringUnityEngine.Testure2D,UnityEngine.FontBitmap等类型呢?

填充字节数组的数据必须来自一个文件类型,该文件类型的数据可以被我们所要转换为的类型所管理?

这目前可行吗?

非常感谢您的任何帮助。


1
一个字节数组就是这样。它是一系列的字节。无法知道这些字节属于字符串、整数、UnityEngine.Font等类型。它们只是字节。您需要通过传递一个Type参数来“反序列化”字节,以便知道它是什么类型的对象。 - Icemanind
哦,太好了。你能给一个快速的例子吗? - user4740550
2
除非它本来就是字符串,否则不要将字节数组转换为字符串。这样做可能会破坏代码。在Net中,Chrs/Strings是两个字节对象,您必须小心使用正确的编码。发送/接收数据通常通过发送字节数组来完成。任何对象都必须被序列化(即转换为字节),然后再进行反序列化。像.png和.jpg这样的二进制数据是单一的字节数组对象,可以简单地转换为字节数组。复杂对象需要更好的字段大小定义,以便在序列化之前进行适当的反序列化。这就是为什么您会看到不同的答案的原因。 - jdweng
非常感谢您提供的信息和建议。 - user4740550
4个回答

54

原始类型很容易,因为它们具有字节数组的定义表示。其他对象则不然,因为它们可能包含无法持久化的内容,例如文件句柄、对其他对象的引用等。

您可以尝试使用BinaryFormatter将对象持久化为字节数组:

public byte[] ToByteArray<T>(T obj)
{
    if(obj == null)
        return null;
    BinaryFormatter bf = new BinaryFormatter();
    using(MemoryStream ms = new MemoryStream())
    {
        bf.Serialize(ms, obj);
        return ms.ToArray();
    }
}

public T FromByteArray<T>(byte[] data)
{
    if(data == null)
         return default(T);
    BinaryFormatter bf = new BinaryFormatter();
    using(MemoryStream ms = new MemoryStream(data))
    {
        object obj = bf.Deserialize(ms);
        return (T)obj;
    }
}

但并非所有类型都可序列化。例如,无法“存储”到数据库的连接。您可以存储用于创建连接的信息(如连接字符串),但无法存储实际的连接对象。


更新

BinaryFormatter现在被认为是“不安全的”,特别是当尝试从不受信任的来源反序列化数据时。这是有道理的,因为您实际上正在将原始二进制数据加载到内存中,可能会做出糟糕的事情。

建议的替代方法是使用非二进制格式(如XML或JSON)来处理通用对象图,或编写自定义二进制序列化代码以显式地序列化基元成员。


我真的很喜欢你的回答,我正在这里测试它。我遇到了一个错误。这是我的代码和出错的位置。 :) - user4740550
我的代码中出现了错误。Byte[] ba = ToByteArray(myStream); //SerializationException: 类型 System.IO.UnmanagedMemoryStream 未标记为可序列化。 - user4740550
2
如果它不可序列化,那么你就不能将其序列化。你打算用序列化的流做什么呢?它只是一种移动数据的机制;它本身没有任何数据。 - D Stanley
4
现在 BinaryFormatter 已经过时且不安全,请阅读 CA2300: 不要使用不安全的反序列化程序 BinaryFormatterBinaryFormatter 安全指南 - Igor

4
你可以像这样将字节数组反序列化为类对象 .Net 6 中的示例。
using System.Text.Json;

using MemoryStream ms = new MemoryStream(bytes);
Examlple ex = JsonSerializer.Deserialize<Example>(ms);
Console.WriteLine(ex.Value);

class Example
{
    string Value {get; set; }
}

2
在C#中,您可以按照以下方法将字节数组转换为任何对象:
byte[] bytesFromBase64 = Convert.FromBase64String(message.Body.ToString());
string stringData = Encoding.UTF8.GetString(bytesFromBase64);
Order order = JsonConvert.DeserializeObject<Order>(stringData);

-9

C++ 模板版本:

template<typename T>
void fromByteArray(T& t, byte *bytes)
{
  t = *(T*)bytes;
};

template<typename T>
byte * toByteArray(T& t) 
{
  return (byte*)&t;
};

该问题已标记为C#。 - Jan Kruse
1
我可以在C# DLL中使用C++ DLL。 - sailfish009

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接