【发布时间】:2021-09-08 19:46:26
【问题描述】:
我有一个方法,在方法内部,我有一个Parallel.ForEach() 来做一些事情。完成后,我希望它立即将所做的事情记录到 JSON 文件中。
目前我有一个单例类,其中包含所有当前 JSON 条目的字典。当stuff完成后,我将新完成的stuff添加到字典中,然后序列化整个字典,然后保存文件。
这很糟糕,尤其是在字典很大的情况下,因为一遍又一遍地序列化大量数据只是浪费时间。如果我可以将stuff 直接保存到 JSON 文件的末尾,我应该可以无缝地完成。
因为我知道我只是在附加数据,所以我想使用 FileStream 来寻找到最后,然后做一些 hack 会起作用,但显然这会弄乱文件的格式。
这是一个例子:
{
"test": {
"id": "test",
"name": "the best test"
},
"test2": {
"id": "test2",
"name": "the second best test"
}
}
附加到 JSON(“伪代码”实际上并不能工作,但你明白了):
FileStream fs = File.OpenWrite("file.json");
fs.Seek(-1, SeekOrigin.End);
await fs.WriteAsync(Encoding.UTF8.GetBytes("},"), 0, 2);
await fs.WriteAsync(jsonAsBytes, 0, jsonAsBytes.Length);
输出:
{
"test": {
"id": "test",
"name": "the best test"
},
"test2": {
"id": "test2",
"name": "the second best test"
},
"test3": {
"id": "test3",
"name": "the third best test"
}
}
有没有更优雅的解决方案?我需要数千次调用这个“添加到 json 文件”方法。如果我在请求/应用程序结束时序列化字典,它不会保存已经发生的事情,这会很糟糕。
【问题讨论】:
-
有更优雅的解决方案吗?是的....使用数据库
-
@Selvin 这是一个单一的二进制控制台应用程序。为此使用数据库,将是 1) 过度杀伤 2) 让用户感到困惑。当然我可以在本地创建一个数据库(如 sqlite),然后创建一个“dump sqlite”命令,生成一个 JSON 文件,但这也不优雅。
-
如果您唯一关心的是格式化,您只需要在每行之前添加两个空格,您的解决方案就可以工作。另一种解决方案是您选择其他 json,例如 yaml,您可以轻松附加到它
-
我不认为,追加似乎是更好的解决方案。只需
fs.Seek(-Encoding.UTF8.GetBytes("\n}").Length-1, SeekOrigin.End);在最后一个元素之后追加。也许 CSV 会更容易处理。