读取字符串时出现OutOfMemoryException

时间:2015-12-23 13:29:03

标签: c# json rest asp.net-web-api json.net

我有一个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

1 个答案:

答案 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