You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用其他序列化器反序列化BinaryFormatter序列化的ConcurrentDictionary?

解决方案:从BinaryFormatter迁移到安全序列化器

核心思路

你之前用BinaryFormatter生成的文件是.NET专属的二进制序列化格式,和JSON、XML、Protobuf等格式完全不兼容,直接用其他序列化器读取必然失败。正确做法是临时用BinaryFormatter读取现有数据,转存为安全序列化器支持的格式,后续业务全程使用新的序列化器读写。

虽然BinaryFormatter存在安全风险,但仅用于读取你自身生成的可信文件时,临时使用是安全的,完成迁移后即可彻底弃用它。


步骤1:迁移现有数据

先编写代码,用BinaryFormatter读取旧文件拿到数据,再用安全序列化器(以Newtonsoft.Json为例)写入新文件:

using System.Collections.Concurrent;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Newtonsoft.Json;

// 原BinaryFormatter生成的旧文件路径
const string OldBinaryFilePath = "your_old_file.bin";
// 新的JSON格式文件路径
const string NewJsonFilePath = "jobs_ack.json";

// 1. 临时用BinaryFormatter读取旧数据
ConcurrentDictionary<string, DateTime> jobsAck;
var binaryFormatter = new BinaryFormatter();
using (var stream = File.Open(OldBinaryFilePath, FileMode.Open))
{
    jobsAck = (ConcurrentDictionary<string, DateTime>)binaryFormatter.Deserialize(stream);
}

// 2. 用Newtonsoft.Json序列化到新文件
var jsonSettings = new JsonSerializerSettings
{
    Formatting = Formatting.Indented, // 可选,格式化输出便于查看
    DateTimeZoneHandling = DateTimeZoneHandling.Utc // 统一时区避免解析异常
};
File.WriteAllText(NewJsonFilePath, JsonConvert.SerializeObject(jobsAck, jsonSettings));

步骤2:后续业务的读写逻辑

迁移完成后,后续创建任务和应用启动加载数据都用Newtonsoft.Json处理:

序列化(创建任务时)

using System.Collections.Concurrent;
using System.IO;
using Newtonsoft.Json;

ConcurrentDictionary<string, DateTime> _jobsAck = new ConcurrentDictionary<string, DateTime>();
// 业务逻辑:向_jobsAck添加任务数据...

const string JsonFilePath = "jobs_ack.json";
var jsonSettings = new JsonSerializerSettings
{
    DateTimeZoneHandling = DateTimeZoneHandling.Utc
};
File.WriteAllText(JsonFilePath, JsonConvert.SerializeObject(_jobsAck, jsonSettings));

反序列化(应用启动时)

using System.Collections.Concurrent;
using System.IO;
using Newtonsoft.Json;

const string JsonFilePath = "jobs_ack.json";
ConcurrentDictionary<string, DateTime> _jobsAck;

if (File.Exists(JsonFilePath))
{
    var jsonContent = File.ReadAllText(JsonFilePath);
    _jobsAck = JsonConvert.DeserializeObject<ConcurrentDictionary<string, DateTime>>(jsonContent);
}
else
{
    _jobsAck = new ConcurrentDictionary<string, DateTime>();
}

可选方案:使用Protobuf-Net

如果偏好二进制格式(体积更小、序列化速度更快),可以用protobuf-net。先安装NuGet包protobuf-net,再按以下代码操作:

迁移代码

using System.Collections.Concurrent;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using ProtoBuf;

const string OldBinaryFilePath = "your_old_file.bin";
const string NewProtobufFilePath = "jobs_ack.pb";

// 读取旧数据
ConcurrentDictionary<string, DateTime> jobsAck;
var binaryFormatter = new BinaryFormatter();
using (var stream = File.Open(OldBinaryFilePath, FileMode.Open))
{
    jobsAck = (ConcurrentDictionary<string, DateTime>)binaryFormatter.Deserialize(stream);
}

// 用Protobuf序列化
using (var stream = File.Open(NewProtobufFilePath, FileMode.Create))
{
    Serializer.Serialize(stream, jobsAck);
}

后续读写

序列化

using System.Collections.Concurrent;
using System.IO;
using ProtoBuf;

ConcurrentDictionary<string, DateTime> _jobsAck = new ConcurrentDictionary<string, DateTime>();
// 业务逻辑:添加任务数据...

const string ProtobufFilePath = "jobs_ack.pb";
using (var stream = File.Open(ProtobufFilePath, FileMode.Create))
{
    Serializer.Serialize(stream, _jobsAck);
}

反序列化

using System.Collections.Concurrent;
using System.IO;
using ProtoBuf;

const string ProtobufFilePath = "jobs_ack.pb";
ConcurrentDictionary<string, DateTime> _jobsAck;

if (File.Exists(ProtobufFilePath))
{
    using (var stream = File.Open(ProtobufFilePath, FileMode.Open))
    {
        _jobsAck = Serializer.Deserialize<ConcurrentDictionary<string, DateTime>>(stream);
    }
}
else
{
    _jobsAck = new ConcurrentDictionary<string, DateTime>();
}

关键说明

  1. 之前直接用XML/JSON/Protobuf读取失败的原因:每个序列化器都有专属格式规范,BinaryFormatter的二进制格式包含.NET类型元数据,和其他序列化器的结构完全不匹配,无法跨格式直接解析。
  2. 迁移完成后建议删除旧的BinaryFormatter生成文件,避免后续误操作。
  3. 序列化器选择:JSON可读性强、调试方便;Protobuf体积小、性能更高,可根据业务需求自行选择。

内容的提问来源于stack exchange,提问作者Vivek Nuna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:17:40