C#对象二进制序列化

35

我想将一个对象进行二进制序列化,并将结果保存到数据库中。

Person person = new Person();
person.Name = "something";

MemoryStream memorystream = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);

我该如何将一个MemoryStream中的字符串转换为字符串类型以保存到数据库,并在需要时反序列化对象?

6个回答

60
你真正需要的是一种安全的方式来表示任意二进制数据为文本,然后再将其转换回来。它存储序列化对象这一事实是无关紧要的。
答案几乎是使用Base 64(例如Convert.ToBase64StringConvert.FromBase64String)。不要使用Encoding.UTF8.GetString或类似的任何东西——你的二进制数据不是编码的文本数据,因此不应该被视为这样处理。
但是,你的数据库没有二进制数据类型吗?检查BLOB、IMAGE和BINARY类型...

字节转字符串 --- 需要一些编码。 - loneshark99
2
@loneshark99:我完全不理解你的评论。如果这是任意二进制数据 - 而不是编码文本 - 那么使用“编码”将是完全错误的方法。 - Jon Skeet
1
我正在学习,但我想知道为什么编码不是正确的方法,而ToBase64String是。 - loneshark99
5
因为“编码(Encoding)”旨在处理固有文本数据 - 它将文本转换为二进制数据,而Base64和十六进制则旨在以文本形式表示固有二进制数据而不丢失信息。 - Jon Skeet
谢谢,这很有道理!我总是对编码感到困惑。谢谢! - loneshark99

45

这是样例。TData必须标记为[Serializable],所有字段类型也必须如此。

    private static TData DeserializeFromString<TData>(string settings)
    {
        byte[] b = Convert.FromBase64String(settings);
        using (var stream = new MemoryStream(b))
        {
            var formatter = new BinaryFormatter();
            stream.Seek(0, SeekOrigin.Begin);
            return (TData)formatter.Deserialize(stream);
        }
    }

    private static string SerializeToString<TData>(TData settings)
    {
        using (var stream = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(stream, settings);
            stream.Flush();
            stream.Position = 0;
            return Convert.ToBase64String(stream.ToArray());
        }
    }

19
//-------write to database-------------------------
Person person = new Person();
person.name = "Firstnm  Lastnm";
MemoryStream memorystream = new MemoryStream(); 
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(memorystream, person);
byte[] yourBytesToDb = memorystream.ToArray();
//here you write yourBytesToDb to database


//----------read from database---------------------
//here you read from database binary data into yourBytesFromDb
MemoryStream memorystreamd = new MemoryStream(yourBytesFromDb);
BinaryFormatter bfd = new BinaryFormatter();
Person deserializedperson = bfd.Deserialize(memorystreamd) as Person;

2
MemoryStream 周围应该加上 using - j00hi
有一个针对 .Net5.0 和其他几个版本的警告:“BinaryFormatter 类型是危险的,不建议用于数据处理。应用程序应尽快停止使用 BinaryFormatter,即使它们认为正在处理的数据是可信的。BinaryFormatter 是不安全的,无法保证安全性。” https://learn.microsoft.com/en-us/dotnet/standard/serialization/binaryformatter-security-guide - Stefan Wuebbe

14

我使用了类似这样的东西

MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, Person);
memoryStream.Flush();
memoryStream.Position = 0;
string value = Convert.ToBase64String(memoryStream.ToArray());

11
在调用ToArray之前不需要倒回MemoryStream - 它返回整个流的数据,而不考虑当前位置。同样,Flush在MemoryStream上无效,尽管对于一般流来说是个好主意。 - Jon Skeet

3

基本上,不要将数据保存为字符串到数据库中,应该使用可用的字段来存储二进制数据。

如果您确实需要将数据作为字符串存储,则需要使用base64编码将byte[]转换为字符串,并使用解码从字符串中获取byte[]。


0

你有没有考虑将MemoryStream转换为Base64Hex字符串,然后放入数据库中?

 byte[] mStream = memorystream.ToArray();
 string sConvertdHex = System.Convert.ToBase64String(mStream)

然后您可以将sConvertdHex的内容存入数据库。要进行反序列化,您需要执行相反的操作

 byte[] mData = System.Convert.FromBase64String(...)

然后将mData反序列化回您的对象。


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