.NET Framework 4.7.2中BinaryFormatter的二进制读写替代方案
.NET Framework 4.7.2下替代BinaryFormatter的二进制读写方案
原代码依赖BinaryFormatter完成ConcurrentDictionary<string, DateTime>的序列化与反序列化,但BinaryFormatter存在严重安全风险,以下是几种适配.NET Framework 4.7.2的替代方案:
方案1:手动基于BinaryWriter/BinaryReader实现
完全原生无依赖,可控性强,安全性高,适合简单类型的序列化场景。
序列化代码
private const string BINARY_FILENAME = "jobsAck.dat"; private ConcurrentDictionary<string, DateTime> _jobsAck; public void SaveToDisk() { using (var stream = File.Open(BINARY_FILENAME, FileMode.Create)) using (var writer = new BinaryWriter(stream)) { // 先写入键值对总数 writer.Write(_jobsAck.Count); foreach (var pair in _jobsAck) { writer.Write(pair.Key); // 将DateTime转为Ticks存储,保证二进制兼容性 writer.Write(pair.Value.Ticks); } } }
反序列化代码
public void LoadFromDisk() { if (!File.Exists(BINARY_FILENAME)) { _jobsAck = new ConcurrentDictionary<string, DateTime>(); return; } using (var stream = File.Open(BINARY_FILENAME, FileMode.Open, FileAccess.Read)) using (var reader = new BinaryReader(stream)) { var count = reader.ReadInt32(); var tempDict = new Dictionary<string, DateTime>(count); for (int i = 0; i < count; i++) { var key = reader.ReadString(); var ticks = reader.ReadInt64(); tempDict[key] = new DateTime(ticks); } _jobsAck = new ConcurrentDictionary<string, DateTime>(tempDict); } }
方案2:使用DataContractSerializer(原生序列化器)
DataContractSerializer是.NET官方提供的安全序列化器,支持强类型校验,无需第三方依赖。
序列化代码
using System.Runtime.Serialization; using System.Xml; public void SaveToDisk() { // 转成普通Dictionary提升兼容性 var dict = new Dictionary<string, DateTime>(_jobsAck); var serializer = new DataContractSerializer(typeof(Dictionary<string, DateTime>)); using (var stream = File.Open(BINARY_FILENAME, FileMode.Create)) using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream)) { serializer.WriteObject(writer, dict); } }
反序列化代码
public void LoadFromDisk() { if (!File.Exists(BINARY_FILENAME)) { _jobsAck = new ConcurrentDictionary<string, DateTime>(); return; } var serializer = new DataContractSerializer(typeof(Dictionary<string, DateTime>)); using (var stream = File.Open(BINARY_FILENAME, FileMode.Open, FileAccess.Read)) using (var reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max)) { var dict = serializer.ReadObject(reader) as Dictionary<string, DateTime>; _jobsAck = dict != null ? new ConcurrentDictionary<string, DateTime>(dict) : new ConcurrentDictionary<string, DateTime>(); } }
方案3:使用Protobuf-Net(第三方高性能序列化库)
基于Google Protocol Buffers实现,序列化后体积小、速度快,安全性高,需通过NuGet安装protobuf-net包适配.NET Framework 4.7.2。
序列化代码
using ProtoBuf; public void SaveToDisk() { // 转普通Dictionary简化序列化逻辑 var dict = new Dictionary<string, DateTime>(_jobsAck); using (var stream = File.Open(BINARY_FILENAME, FileMode.Create)) { Serializer.Serialize(stream, dict); } }
反序列化代码
public void LoadFromDisk() { if (!File.Exists(BINARY_FILENAME)) { _jobsAck = new ConcurrentDictionary<string, DateTime>(); return; } using (var stream = File.Open(BINARY_FILENAME, FileMode.Open, FileAccess.Read)) { var dict = Serializer.Deserialize<Dictionary<string, DateTime>>(stream); _jobsAck = new ConcurrentDictionary<string, DateTime>(dict); } }
内容的提问来源于stack exchange,提问作者Vivek Nuna
相关产品推荐
相关产品推荐

