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

使用JsonSerializer.Serialize(Utf8JsonWriter)写入JSON文件后文件被占用无法访问的问题排查

JsonSerializer.Serialize(Utf8JsonWriter)写入JSON文件后文件被占用无法访问的问题排查

这个问题的核心原因是你没有正确释放File.Create()返回的FileStream资源,导致文件句柄没有被系统及时回收,从而引发文件被占用的异常。

为什么第一个写法会出问题?

在你的第一段代码里:

string pathOfRelevantStuff = "path";
string fileOfRelevantStuff = Path.Combine(pathOfRelevantStuff, $"fileName_1.json");
Utf8JsonWriter relevantDataWriter = new(File.Create(fileOfRelevantStuff));
JsonSerializer.Serialize(relevantDataWriter, dataToBeReadLater);
relevantDataWriter.Flush();
relevantDataWriter.Dispose();

你直接把File.Create()返回的FileStream传给了Utf8JsonWriter的构造函数,但没有对这个FileStream做任何资源管理操作。虽然你手动调用了relevantDataWriter.Dispose(),但在.NET 7的Utf8JsonWriter实现中,即使默认配置会在Dispose时尝试关闭底层流,仍可能存在边界情况导致流没有被正确释放——更关键的是,手动管理资源的方式本身就不可靠,很容易因为代码路径变化(比如中途抛出异常)导致资源泄漏。

你调试时在Dispose()之后仍无法打开文件,就是因为底层的文件句柄还没被系统彻底释放。

为什么Workaround能正常工作?

你的第二个写法用StreamWriter结合File.CreateText(),并且手动调用了Close()和Dispose():

StreamWriter relevantDataWriter = File.CreateText(fileOfRelevantStuff);
// ...
relevantDataWriter.Close();
relevantDataWriter.Dispose();

File.CreateText()返回的StreamWriter会自动绑定并管理底层的文件流,调用Close()或Dispose()时会确保底层文件句柄被正确释放,所以不会出现文件占用的问题。

正确的修复方式

最可靠的做法是使用**using语句**自动管理所有实现IDisposable接口的资源(包括FileStream和Utf8JsonWriter),这样无论代码是否抛出异常,资源都会被自动释放:

string pathOfRelevantStuff = "path";
string fileOfRelevantStuff = Path.Combine(pathOfRelevantStuff, $"fileName_1.json");

// 使用using包裹FileStream和Utf8JsonWriter,确保资源自动释放
using var fileStream = File.Create(fileOfRelevantStuff);
using var relevantDataWriter = new Utf8JsonWriter(fileStream);
JsonSerializer.Serialize(relevantDataWriter, dataToBeReadLater);
// 不需要手动调用Flush和Dispose,using块结束时会自动处理

如果一定要手动管理资源(不推荐),需要确保同时释放FileStream和Utf8JsonWriter:

string pathOfRelevantStuff = "path";
string fileOfRelevantStuff = Path.Combine(pathOfRelevantStuff, $"fileName_1.json");
FileStream fileStream = null;
Utf8JsonWriter relevantDataWriter = null;
try
{
    fileStream = File.Create(fileOfRelevantStuff);
    relevantDataWriter = new Utf8JsonWriter(fileStream);
    JsonSerializer.Serialize(relevantDataWriter, dataToBeReadLater);
    relevantDataWriter.Flush();
}
finally
{
    relevantDataWriter?.Dispose();
    fileStream?.Dispose();
}

额外提示

  1. Utf8JsonWriter.Dispose()会自动调用Flush(),所以手动调用Flush()是多余的,可以省略。
  2. 始终优先使用using语句(C# 8+支持using var语法,更简洁)来管理可释放资源,这是.NET中避免资源泄漏的最佳实践。
  3. 你遇到的问题在.NET 7的后续版本中可能已经被修复,但使用using语句的写法在任何版本中都是安全可靠的。

备注:内容来源于stack exchange,提问作者Jean-David Lanz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 18:04:50