binaryformatter 已被弃用且不安全,应改用 system.text.json(推荐)、messagepack 或 protocol buffers;json 适合文本数据,二进制内容需 base64 编码或单独存储。

用 BinaryFormatter 保存二进制文件?别用了
从 .NET Core 3.0 开始,BinaryFormatter 已被标记为过时(obsolete),且默认禁用——它存在严重反序列化安全风险,微软明确不推荐在任何新项目中使用。即使你强制启用,.NET 6+ 也会在运行时抛出 NotSupportedException。
如果你真需要二进制序列化(比如老系统兼容、高性能本地缓存),可改用 System.Text.Json 的二进制编码变体(需搭配 JsonSerializerOptions + Utf8JsonWriter 写入 MemoryStream),但更现实的选择是:直接用 JSON,或换用 MessagePack 这类安全、紧凑的二进制格式。
- 不要在生产环境写
new BinaryFormatter().Serialize(...) - 若必须读取旧的
.bin文件,用BinaryFormatter仅限于可信、隔离的脱机场景,并确保反序列化类型白名单严格控制 - 替代方案优先级:JSON(通用)→ MessagePack(紧凑+快)→ Protocol Buffers(跨语言)
用 System.Text.Json 序列化到 JSON 文件(推荐)
System.Text.Json 是 .NET 5+ 默认内置的高性能 JSON 库,无需安装 NuGet,支持异步、流式读写、自定义转换器,且默认忽略循环引用(不会崩溃)。
最简保存方式:
var options = new JsonSerializerOptions { WriteIndented = true };
File.WriteAllText("user.json", JsonSerializer.Serialize(user, options));
注意几个关键点:
-
WriteIndented = true仅用于调试,生产环境建议关掉以减小体积 - 若对象含
DateTime,默认序列化为 ISO 8601 字符串(如"2024-05-20T14:30:00Z"),无需额外配置 - 私有字段默认不序列化;要包含,加
[JsonPropertyName("xxx")]或设置IncludeFields = true和DefaultIgnoreCondition = JsonIgnoreCondition.Never - 遇到
NotSupportedException(如含DBNull、IntPtr或自定义不可序列化类型),说明该类型没实现JsonConverter,需手动注册转换器
用 Newtonsoft.Json(Json.NET)保存时要注意什么
虽然 System.Text.Json 是官方推荐,但很多老项目仍依赖 Newtonsoft.Json。它更灵活,但也更容易踩坑。
基础写法:
File.WriteAllText("user.json", JsonConvert.SerializeObject(user, Formatting.Indented));
常见陷阱:
- 默认会序列化所有 public 属性和字段,包括
get; set;自动属性的 backing field(如果用了[JsonIgnore]就没事) -
DateTime默认按本地时区输出,易引发时区混淆;建议统一用JsonConvert.SerializeObject(..., new JsonSerializerSettings { DateTimeZoneHandling = DateTimeZoneHandling.Utc }) - 若对象里有
JObject或JArray,它们会被原样嵌入,但后续用System.Text.Json读取会失败——混用库时务必统一序列化格式 - 大对象(>85KB)可能触发 LOH(Large Object Heap)分配,频繁操作影响 GC 性能;此时应改用
JsonTextWriter流式写入
异步保存和错误处理不能省
直接调用 File.WriteAllText 会阻塞线程,尤其在 UI 或 ASP.NET Core 请求线程中容易拖慢响应。真正可用的写法是异步 + 异常包裹:
try
{
var json = JsonSerializer.Serialize(user, new JsonSerializerOptions { WriteIndented = false });
await File.WriteAllTextAsync("user.json", json);
}
catch (UnauthorizedAccessException)
{
// 检查目录是否有写权限,或文件是否被其他进程占用(如 Excel 正在打开该文件)
}
catch (IOException ex) when (ex.Message.Contains("The process cannot access the file"))
{
// 文件被独占锁定,考虑加重试或提示用户关闭相关程序
}
另外,路径必须合法:Directory.CreateDirectory(Path.GetDirectoryName("data/user.json")) 要提前执行,否则 File.WriteAllTextAsync 会直接抛 DirectoryNotFoundException。
最后提醒:JSON 不适合存二进制数据(如图片、音频)。这类内容应 Base64 编码后作为字符串字段存入,但体积膨胀约 33%;更合理的方式是单独保存为文件,JSON 中只存路径或哈希值。










