2012-10-30 13 views
10

मेरे पास एक बहुत बड़ी चार सरणी है जिसे मुझे रेगेक्स का उपयोग करने के लिए स्ट्रिंग में कनवर्ट करने की आवश्यकता है।
लेकिन यह इतना बड़ा है कि जब मैं इसे स्ट्रिंगर स्ट्रिंग करने के लिए पास करता हूं तो मुझे OutOfMemoryException मिलता है।इसे कॉपी किए बिना चार सरणी से स्ट्रिंग कैसे बनाएं?

मुझे पता है कि स्ट्रिंग अपरिवर्तनीय और इसलिए यह उसके अंतर्निहित चरित्र संग्रह बताना संभव नहीं होना चाहिए, लेकिन मैं पूरी बात को कॉपी किए बिना उस पर रेगुलर एक्सप्रेशन का उपयोग करने के लिए एक तरह से की जरूरत है।

मैं उस सरणी को कैसे प्राप्त करूं?

  • मुझे StreamReader का उपयोग करके फ़ाइल से मिलता है। मुझे शुरुआती स्थिति और पढ़ने की सामग्री की लंबाई, Read और ReadBlock विधियों को मुझे char[] बफर की आपूर्ति करने की आवश्यकता है।

    • वहां एक स्ट्रिंग के अंतर्निहित संग्रह निर्दिष्ट करने के लिए एक रास्ता है:

    तो यहाँ बातें मैं जानना चाहता हूँ कर रहे हैं? (क्या यह अपने सर को सरणी में भी रखता है?)

  • ... या रेगेक्स का उपयोग सीधे चार सरणी पर कर रहा है?
  • ... या सीधे फ़ाइल के हिस्से को स्ट्रिंग के रूप में प्राप्त करना?
+2

रेगेक्स क्या है? यदि यह काफी आसान है तो आप उसे कोड के साथ बदल सकते हैं जो 'char []' चलता है। –

+0

'char []' कितना बड़ा है? –

+0

@ मैट: दुर्भाग्य से मैं नहीं कर सकता। यह एक बहुत लंबा और जटिल पार्सर है। –

उत्तर

1

मुझे लगता है कि आपकी सबसे अच्छी शर्त अलग-अलग तारों [] हिस्सों को अलग-अलग तारों में पढ़ने के लिए होगी जो एक निश्चित आयाम के साथ ओवरलैप हो। इस तरह आप अलग-अलग हिस्सों पर अपना रेगेक्स निष्पादित करने में सक्षम होंगे, और ओवरलैप आपको यह सुनिश्चित करने की क्षमता प्रदान करेगा कि भाग में "ब्रेक" खोज पैटर्न को तोड़ नहीं देता है। एक छद्म-कोड तरीके में:

int chunkSize = 100000; 
int overLap = 2000; 

for(int i = 0; i < myCharArray.length; i += chunkSize - overlap) 
{ 
    // Grab your array chunk into a partial string 
    // By having your iteration slightly smaller than 
    // your chunk size you guarantee not to miss any 
    // character groupings. You just need to make sure 
    // your overlap is sufficient to cover the expression 
    string chunk = new String(myCharArray.Skip(i).Take(chunkSize).ToArray()); 
    // run your regex 
} 
+1

एक टिप्पणी: लिंक विधियों का उपयोग करने का कोई कारण नहीं है ' छोड़ें 'और' टेक '। स्ट्रिंग कन्स्ट्रक्टर का एक अधिभार है (http://msdn.microsoft.com/en-us/library/ms131424.aspx) इस तरह की चीजें करने के लिए। साथ ही, लिंक विधि 'ToArray() 'डेटा को एक अतिरिक्त समय की प्रतिलिपि बनायेगी। –

+0

+1। ओवरलैप्ड हिस्सों के साथ पढ़ना सी # में अज्ञात रेगेक्स के साथ मेल खाने के लिए उचित दृष्टिकोण प्रतीत होता है। टिप्पणी पर टिप्पणी: मुझे लगता है कि नमूना में छोड़ें/लेना ठीक है क्योंकि यह इरादा अच्छी तरह दिखाता है, और यह स्पष्ट रूप से गलत काम करने की संभावना है ताकि कॉपी-पेस्ट के रूप में सीधे उपयोग न किया जा सके। –

+0

@JeppeStigNielsen: यह सिर्फ psuedo-code होने के लिए था और सबसे अच्छी सी # विधि को देखने के बजाय मैं नियमित रूप से टाइप करने वाले कुछ चीज़ों के साथ चला गया जो मेरा बिंदु मिला। अगर कोई उपर्युक्त कोड क्रियान्वयन को लागू करना चाहता था तो मैं उनकी संवेदना पर सवाल उठाऊंगा। –

-1

आप .NET 4.0 या अधिक प्रयोग कर रहे हैं, का उपयोग कर आप क्या होना चाहिए एक MemoryMappedFile है। इस वर्ग को विशेष रूप से डिजाइन किया गया था ताकि आप बहुत बड़ी फाइलों में हेरफेर कर सकें। MSDN प्रलेखीकरण से:

एक स्मृति-मैप की गई फ़ाइल एक आवेदन के तार्किक पता अंतरिक्ष के लिए एक फ़ाइल की सामग्री को मैप करता है। मेमोरी-मैप की गई फाइलें प्रोग्रामर को बेहद बड़ी फाइलों के साथ काम करने में सक्षम बनाती हैं क्योंकि मेमोरी को समवर्ती रूप से प्रबंधित किया जा सकता है, और वे बिना किसी मांग की आवश्यकता के फ़ाइल पर पूर्ण, यादृच्छिक पहुंच की अनुमति देते हैं। मेमोरी-मैप की गई फ़ाइलों को कई प्रक्रियाओं में भी साझा किया जा सकता है।

एक बार जब आप अपनी मेमोरी मैप की गई फ़ाइल प्राप्त कर लेते हैं, तो मेमोरी मैप किए गए फ़ाइल में RegEx को कैसे लागू करें, this Stack Overflow answer देखें।

आशा है कि इससे मदद मिलती है!

+0

-1। सुनिश्चित नहीं है कि MemoryMappedFile का उपयोग क्यों करना StreamReader से बेहतर होगा (किसी को हाथ से एन्कोडिंग से निपटना होगा) ... यह भी अस्पष्ट है कि बाइट एरे पर रेगेक्स चलाने के लिए जावा के कोड के लिए मिलान सी # कार्यान्वयन कहां प्राप्त करें। –

+0

@AlexeiLevenkov - MemoryMappedFile StreamReader से बेहतर है क्योंकि StreamReader पूरी फ़ाइल को स्मृति में पढ़ता है। MemoryMappedFile फ़ाइल को विंडो या दृश्यों में विभाजित करता है जो आपको फ़ाइल के किसी विशिष्ट क्षेत्र पर संचालित करने की अनुमति देता है। MemoryMappedFile केवल पूरी चीज की बजाय आपको आवश्यक बाइट्स की मात्रा में पढ़ता है। – Icemanind

+4

@icemanind: गलत। StreamReader पूरी फ़ाइल को स्मृति में नहीं पढ़ता है। – SLaks

1

एक बदसूरत विकल्प एक अप्रबंधित RegEx लाइब्रेरी (जैसे POSIX नियमित अभिव्यक्ति लाइब्रेरी) और असुरक्षित कोड का उपयोग करना होगा। आप चार सरणी में बाइट * पॉइंटर प्राप्त कर सकते हैं और इसे सीधे अप्रबंधित लाइब्रेरी में भेज सकते हैं, फिर प्रतिक्रियाओं को पीछे छोड़ दें।

fixed (byte * pArray = largeCharArray) 
{ 
    // call unmanaged code with pArray 
} 
1

आप एक चरित्र या पैटर्न है कि आपको लगता है कि गारंटी है पैटर्न आप खोजने की कोशिश कर रहे हैं में नहीं खोज सकते है, तो आप उस चरित्र के लिए सरणी स्कैन और छोटे तार व्यक्तिगत रूप से कार्रवाई करने के लिए बना सकते हैं । प्रक्रिया होगी कुछ की तरह:

char token = '|'; 
int start = 0; 
int length = 0; 
for(int i = 0; i < charArray.Length; i++;) 
{ 
    if(charArray[i] == token) 
    { 
     string split = new string(charArray,start,length); 
     // check the string using the regex 

     // reset the length 
     length = 0; 
    } 
    else 
    { 
     length++; 
    } 
} 

इस तरह आप स्ट्रिंग कि बनाम पूरी स्ट्रिंग प्रत्येक प्रयास के बाद GCed होगा के छोटे खंडों कॉपी कर रहे हैं।

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