我有一个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但未在用户代码中处理
该机器运行64位窗口,内存为16Gb。
那么,我的选择是什么?
我想要的只是来自(非常大)IQueryable<MyObject>
字符串的JSON
。
答案 0 :(得分:8)
你的代码基本上模仿StreamReader.ReadToEnd所做的事情,至少需要读取大响应所需内存的4倍(字符串响应本身的内存,StringBuilder的内部缓冲区,所有内容的大小)中间临时字符串和最终字符串)。
您可以通过使用JsonTextReader直接从流中反序列化来避免这种情况。从documentation sample:
复制using (var json= new JsonTextReader(streamReader))
{
JsonSerializer serializer = new JsonSerializer();
return (List<MyObject>)serializer.Deserialize(json, typeof(List<MyObject>));
}
0