2009-09-10 16 views
8

मैं टैब अलग फ़ाइल पढ़ने के लिए अपने सी # कोड में string.split() का उपयोग कर रहा हूं। मुझे कोड आउटपुट में नीचे उल्लिखित "आउटऑफमेमरी अपवाद" का सामना करना पड़ रहा है।string.split() "अलग अपवाद से बाहर" टैब अलग फ़ाइल पढ़ने पर

यहां मैं जानना चाहूंगा कि फाइल 16 एमबी आकार के लिए समस्या क्यों आ रही है?

यह सही दृष्टिकोण है या नहीं?

using (StreamReader reader = new StreamReader(_path)) 
{ 
    //...........Load the first line of the file................ 
    string headerLine = reader.ReadLine(); 

    MeterDataIPValueList objMeterDataList = new MeterDataIPValueList(); 
    string[] seperator = new string[1]; //used to sepreate lines of file 

    seperator[0] = "\r\n"; 
    //.............Load Records of file into string array and remove all empty lines of file................. 
    string[] line = reader.ReadToEnd().Split(seperator, StringSplitOptions.RemoveEmptyEntries); 
    int noOfLines = line.Count(); 
    if (noOfLines == 0) 
    { 
    mFileValidationErrors.Append(ConstMsgStrings.headerOnly + Environment.NewLine); 
    } 
    //...............If file contains records also with header line.............. 
    else 
    { 
    string[] headers = headerLine.Split('\t'); 
    int noOfColumns = headers.Count(); 

    //.........Create table structure............. 
    objValidateRecordsTable.Columns.Add("SerialNo"); 
    objValidateRecordsTable.Columns.Add("SurveyDate"); 
    objValidateRecordsTable.Columns.Add("Interval"); 
    objValidateRecordsTable.Columns.Add("Status"); 
    objValidateRecordsTable.Columns.Add("Consumption"); 

    //........Fill objValidateRecordsTable table by string array contents ............ 

    int recordNumber; // used for log 
    #region ..............Fill objValidateRecordsTable..................... 
    seperator[0] = "\t"; 
    for (int lineNo = 0; lineNo < noOfLines; lineNo++) 
    { 
     recordNumber = lineNo + 1; 
     **string[] recordFields = line[lineNo].Split(seperator, StringSplitOptions.RemoveEmptyEntries);** // Showing me error when we split columns 
     if (recordFields.Count() == noOfColumns) 
     { 
     //Do processing 
     } 
+4

एक तरफ, एरिक लिपर्ट के पास आउटऑफमेमरी अपवादों पर एक महान ब्लॉग है। http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx –

+0

क्या यह कॉम्पैक्ट फ्रेमवर्क पर है (यानी विंडोज मोबाइल)? – MusiGenesis

उत्तर

12

स्प्लिट खराब कार्यान्वित किया जाता है, और गंभीर प्रदर्शन मुद्दा जब है विशाल तारों पर लागू this article for details on memory requirements by split function का संदर्भ लें:

जब आप एक स्ट्रिंग प्रत्येक 16 अक्षरों के 1,355,049 अल्पविराम से अलग स्ट्रिंग से युक्त पर एक विभाजन कर क्या होता है, 25,745,930 की कुल वर्ण की हो रही है?

  1. स्ट्रिंग वस्तु की ओर इशारा की एक सरणी: 4 (पता सूचक) से सटे वर्चुअल ऐड्रेस स्पेस * 1,355,049 = 5,420,196 (सरणियों आकार) + 16 = 5420212.

  2. गैर (बही खाता के लिए) 1355049 तारों के लिए संगत वर्चुअल एड्रेस स्पेस, 54 बाइट्स में से प्रत्येक। इसका मतलब यह नहीं है कि उन सभी 1.3 मिलियन तारों को पूरे ढेर में बिखराया जाएगा, लेकिन उन्हें LOH पर आवंटित नहीं किया जाएगा। जीसी उन्हें जेन 0 ढेर पर बंच पर आवंटित करेगा।

  3. Split.Function System.Int32 के आंतरिक सरणी पैदा करेगा [] आकार 25,745,930, उपभोक्ता (102,983,736 बाइट्स) की ~ LOH है, जो बहुत महंगा है एल

1

संपूर्ण सामग्री को विभाजित करने के बजाय फ़ाइल को लाइनवाई पढ़ने का प्रयास करें।

10

एक सरणी पहले "reader.ReadToEnd()" लाइन सीधे द्वारा फ़ाइल लाइन पढ़ें में पूरी फ़ाइल को पढ़ने की कोशिश करो नहीं ..

using (StreamReader sr = new StreamReader(this._path)) 
     { 
      string line = ""; 
      while((line= sr.ReadLine()) != null) 
      { 
       string[] cells = line.Split(new string[] { "\t" }, StringSplitOptions.None); 
       if (cells.Length > 0) 
       { 

       } 
      } 
     } 
+0

जब हम लाइन –

+1

द्वारा लाइन पढ़ते हैं तो यह प्रभाव डालता है यदि यह मेरा काम केवल एक पंक्ति में है तो यह काम नहीं करता है। – Butzke

4

मैं सिफारिश करेंगे की 98MB यदि आप कर सकते हैं लाइन-दर-रेखा पढ़ना, लेकिन कभी-कभी नई लाइनों द्वारा विभाजित करना आवश्यक नहीं है।

तो आप हमेशा अपनी याददाश्त कुशल विभाजन लिख सकते हैं। इसने मेरे लिए समस्या हल की।

private static IEnumerable<string> CustomSplit(string newtext, char splitChar) 
    { 
     var result = new List<string>(); 
     var sb = new StringBuilder(); 
     foreach (var c in newtext) 
     { 
      if (c == splitChar) 
      { 
       if (sb.Length > 0) 
       { 
        result.Add(sb.ToString()); 
        sb.Clear(); 
       } 
       continue; 
      } 
      sb.Append(c); 
     } 
     if (sb.Length > 0) 
     { 
      result.Add(sb.ToString()); 
     } 
     return result; 
    } 
2

मैं अपना खुद का उपयोग करता हूं। इसका परीक्षण 10 यूनिट परीक्षणों के साथ किया गया है ..

public static class StringExtensions 
{ 

    // the string.Split() method from .NET tend to run out of memory on 80 Mb strings. 
    // this has been reported several places online. 
    // This version is fast and memory efficient and return no empty lines. 
    public static List<string> LowMemSplit(this string s, string seperator) 
    { 
     List<string> list = new List<string>(); 
     int lastPos = 0; 
     int pos = s.IndexOf(seperator); 
     while (pos > -1) 
     { 
      while(pos == lastPos) 
      { 
       lastPos += seperator.Length; 
       pos = s.IndexOf(seperator, lastPos); 
       if (pos == -1) 
        return list; 
      } 

      string tmp = s.Substring(lastPos, pos - lastPos); 
      if(tmp.Trim().Length > 0) 
       list.Add(tmp); 
      lastPos = pos + seperator.Length; 
      pos = s.IndexOf(seperator, lastPos); 
     } 

     if (lastPos < s.Length) 
     { 
      string tmp = s.Substring(lastPos, s.Length - lastPos); 
      if (tmp.Trim().Length > 0) 
       list.Add(tmp); 
     } 

     return list; 
    } 
} 
संबंधित मुद्दे