c# - 读取字符串时出现 OutOfMemoryException

标签 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();

完整的错误是:

An exception of type 'System.OutOfMemoryException' occurred in mscorlib.dll but was not handled in user code

机器运行 64 位 Windows,内存为 16Gb。

那么,我有哪些选择?

我只想要一个 IQueryable<MyObject>来自(非常大)JSON字符串。

最佳答案

您的代码本质上模拟了 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>));
}

关于c# - 读取字符串时出现 OutOfMemoryException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34436804/

相关文章:

java - C# IEnumerable 相当于 java Iterator 的 next() 方法?

python - 在 python 中解析 JSON 时出错

html - 使用 Node.js 发送 POST JSON 数据并接收(无 BODYPARSER)

web-services - 错误 HTTP 状态 406 : @ResponseBody not returning data

c# - DNN 6 在登录页面隐藏找回密码

c# - 触摸屏键盘

c# - 使用 EF 调用 oracle 存储过程失败

javascript - 如何使用 Lo-dash 在 _.filter 的回调函数中迭代数组

java - 如何使用简单的html表单从rest服务中获取值(value)?

wcf - POST/PUT静态服务的URI模板