我正在使用带有JsonTextReader的StreamReader来反序列化包含数万个小对象的大型 JSON文件,并且它消耗的内存比我想象的更合理(并且耗尽).我正在使用我理解的是读取大文件的推荐模式.
为说明目的而简化的代码:
using (StreamReader streamReader = new StreamReader(stream))
using (JsonTextReader reader = new JsonTextReader(streamReader))
{
JToken token;
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
token = JToken.Load(reader);
RawResult result = token.ToObject<RawResult>();
results.Add(result);
}
}
VS2015内存分析器告诉我,大多数内存都被Newtonsoft.Json.Linq.JValue对象占用,这很奇怪,因为一旦当前令牌转换为ToObject(),就没有理由(就我而言) )为什么它不应该被丢弃.
我假设Newtonsoft库保留了迄今为止在内存中解析的所有JSON.我不需要它这样做,我想如果我能防止这种情况,我的记忆问题就会消失.
可以做些什么?
最佳答案 看起来你不需要使用JTokens作为中间人;您可以直接反序列化到循环内的RawResult类.
using (StreamReader streamReader = new StreamReader(stream))
using (JsonTextReader reader = new JsonTextReader(streamReader))
{
var serializer = new JsonSerializer();
while (reader.Read() && reader.TokenType != JsonToken.EndArray)
{
RawResult result = serializer.Deserialize<RawResult>(reader);
results.Add(result);
}
}
另请注意,通过将结果项添加到列表中,您可以将它们全部保留在内存中.如果您可以一次处理一个并将每个结果分别写入输出(文件,数据库,网络流等),您也可以通过这种方式节省内存.
RawResult result = serializer.Deserialize<RawResult>(reader);
ProcessResult(result); // process result now instead of adding to a list