我有一个C#.NET系统,它接受JSON
数据馈送并使用Newtonsoft.Json.JsonConvert.DeserializeObject
转换器将其转换为对象。
只要JSON字符串低于一定大小(几Mb),这个过程就可以完美工作,但一旦返回的数据很大(几乎100Mb),我就会得到错误OutOfMemoryException
此代码适用于小数据:
// WebClient ------------------------------------------------------------------
var _client = new System.Net.WebClient();
var _content = _client.DownloadString(_url);
但在最后一行(DownloadString
)上爆炸
我试着改为这个,它也适用于小数据,但当数据大小增加时,它在ReadToEnd
行上仍然失败了。
using (var _response = (System.Net.HttpWebResponse)_request.GetResponse())
{
using (System.IO.Stream _dataStream = _response.GetResponseStream())
{
using (System.IO.StreamReader _streamReader = new System.IO.StreamReader(_dataStream))
{
string _responseFromServer = _streamReader.ReadToEnd();
}
}
}
最后我尝试了这个,它起了作用:
StringBuilder _stringBuilder = new StringBuilder();
using (var _response = (System.Net.HttpWebResponse)_request.GetResponse())
{
using (System.IO.Stream _dataStream = _response.GetResponseStream())
{
using (System.IO.StreamReader _streamReader = new System.IO.StreamReader(_dataStream))
{
while (!streamReader.EndOfStream)
{
char[] _buffer = new char[4096];
_streamReader.ReadBlock(_buffer, 0, _buffer.Length);
var _bufferString = new String(_buffer);
_stringBuilder.Append(_bufferString);
}
}
}
}
但当它到达下一行时,出现了OutOfMemoryException
错误:
var _results = Newtonsoft.Json.JsonConvert.DeserializeObject<List<MyObject>>(_stringBuilder.ToString());
它不喜欢ToString()
方法。
它还坠毁了一条像这样的简单线路
string _convertedString = _stringBuilder.ToString();
完整错误为:
中发生类型为"System.OutOfMemoryException"的异常mscorlib.dll,但未在用户代码中处理
该机器正在运行具有16Gb内存的64位窗口。
那么,我有什么选择?
我想要的只是一个(非常大的)JSON
字符串中的IQueryable<MyObject>
。
您的代码基本上模拟了StreamReader.ReadToEnd的操作,读取一个大响应所需的内存至少是它的4倍(字符串响应本身的内存、StringBuilder的内部缓冲区、所有中间临时字符串和最终字符串的大小)。
您可以通过使用JsonTextReader直接从流进行反序列化来避免这种情况。从文档样本复制:
using (var json= new JsonTextReader(streamReader))
{
JsonSerializer serializer = new JsonSerializer();
return (List<MyObject>)serializer.Deserialize(json, typeof(List<MyObject>));
}
O