我有一个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>(_stringBuilder.ToString());
它不喜欢这种ToString()
方法.
它也像一条简单的线坠毁了
string _convertedString = _stringBuilder.ToString();
完整的错误是:
mscorlib.dll中出现"System.OutOfMemoryException"类型的异常,但未在用户代码中处理
该机器运行64位窗口,内存为16Gb.
那么,我的选择是什么?
我想要的只是IQueryable
一个(非常大的)JSON
字符串.
您的代码基本上模拟了StreamReader.ReadToEnd所做的事情,至少占用了读取大响应所需内存的4倍(字符串响应本身的内存,StringBuilder的内部缓冲区,所有中间临时字符串的大小和最终字符串) .
您可以通过使用JsonTextReader直接从流中反序列化来避免这种情况.从文档示例中复制:
using (var json= new JsonTextReader(streamReader)) { JsonSerializer serializer = new JsonSerializer(); return (List)serializer.Deserialize(json, typeof(List )); }
Ø