2015-12-23 9 views
7

पढ़ते समय मेरे पास एक सी # .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 में हुआ लेकिन में संभाला नहीं गया था उपयोगकर्ता कोड

मशीन 16 जीबी मेमोरी के साथ 64 बिट विंडोज़ चल रही है।

तो, मेरे विकल्प क्या हैं?

मैं चाहता हूं कि एक IQueryable<MyObject> एक (बहुत बड़ी) JSON स्ट्रिंग से है।

+1

चेक बाहर इस प्रश्न के लिए जवाब है, http://stackoverflow.com/questions/27315521/system-outofmemoryexception-with-json-net-with-listobject, एक समय में एक वस्तु को deserializes – dbugger

+2

एक आउटऑफमेमरी अपवाद विभिन्न कारणों से हो सकता है, जैसे थकाऊ बफर, जीडीआई ऑब्जेक्ट इत्यादि। अपवाद का कॉल स्टैक आपको बताएगा कि यह कहां हुआ, लेकिन असली अपराधी अक्षम कोड है। * जब आप StreamReader के माध्यम से डेटा पढ़ सकते हैं तो आप स्ट्रिंगबिल्डर का उपयोग क्यों कर रहे हैं? आप जो कर रहे हैं वह 'StreamReader से बेहतर नहीं है (या अधिक कुशल)।ReadToEnd() '। –

+0

@ पानागियोटिस कानावोस - वे केवल विभिन्न विधियां हैं जिन्हें मैंने प्रक्रियाओं को दिखाने के लिए काम करने के लिए कोशिश की है। यदि StreamReader में Deserializer में स्मृति त्रुटि के बिना मान प्राप्त करने का कोई तरीका था तो मुझे जानना अच्छा लगेगा। – DeclanMcD

उत्तर

7

आपका कोड अनिवार्य रूप से अनुकरण करता है कि StreamReader.ReadToEnd क्या बड़ी प्रतिक्रिया को पढ़ने के लिए स्मृति की कम से कम 4 बार लेता है (स्ट्रिंग प्रतिक्रिया की स्मृति, स्ट्रिंगबिल्डर का आंतरिक बफर, सभी मध्यवर्ती अस्थायी तारों का आकार और अंतिम स्ट्रिंग)।

आप सीधे JsonTextReader के साथ स्ट्रीम से deserializing द्वारा इसे से बच सकते हैं। documentation sample से प्रतिलिपि बनाई जा रही:

using (var json= new JsonTextReader(streamReader)) 
{ 
    JsonSerializer serializer = new JsonSerializer(); 
    return (List<MyObject>)serializer.Deserialize(json, typeof(List<MyObject>)); 
} 

हे

+0

सही! पहली बार एक इलाज किया - बस आपके कोड में मामूली परिवर्तन - शब्द को jsonTextReader में बदल दिया – DeclanMcD

संबंधित मुद्दे