2010-01-27 10 views
6

मेरे पास एक फ़ाइल है जिसमें से मैंने डेटा पढ़ा है। इस फ़ाइल से सभी पाठ एक स्ट्रिंग चर (एक बहुत बड़ा चर) में संग्रहीत है। फिर मेरे ऐप के दूसरे हिस्से में मैं इस स्ट्रिंग के माध्यम से चलना चाहता हूं और उपयोगी जानकारी निकाल सकता हूं, चरण-दर-चरण (स्ट्रिंग को पार्स करना)।बड़े तारों और सीमित मेमोरी से निपटने के लिए कैसे करें

इस बीच मेरी स्मृति पूरी हो जाती है और आउटऑफमेमरी अपवाद मुझे आगे की प्रक्रिया से रोकता है। मुझे लगता है कि फ़ाइल से इनपुटस्ट्रीम पढ़ने के दौरान डेटा को सीधे संसाधित करना बेहतर होगा। लेकिन संगठनात्मक उद्देश्यों के लिए, मैं अपने आवेदन में स्ट्रिंग को दूसरे भाग में पास करना चाहता हूं।

स्मृति को बहने से रोकने के लिए मुझे क्या करना चाहिए?

+0

क्या आप पाठकों में से किसी एक के साथ पाठ बिट को पार्स नहीं कर सकते (उदा। BufferedReader)? –

उत्तर

7

आपको इसे सभी को एक बड़ी स्ट्रिंग में संग्रहीत करने के बजाय BufferedInputReader का उपयोग करना चाहिए।

यदि आप जो भी पार्स करना चाहते हैं, उसी पंक्ति पर होता है, तो StringTokenizer काफी अच्छी तरह से काम करेगा, अन्यथा आपको फ़ाइल से जो कुछ भी आप चाहते हैं उसे पढ़ने के लिए एक तरीका तैयार करना होगा, फिर प्रत्येक को स्ट्रिंगटोकनाइज़र लागू करें बयान।

+0

+1। एंथनी: सामान्य विचार यह है कि आप कर्सर पास करते हैं (जैसे डीबी में)। वे पाठ के मामले में पाठक हो सकते हैं, बाइट्स के मामले में धाराएं, आइटम के अनुक्रम के मामले में इटरेटर, या जो कुछ भी हो। आप एक प्रकार को दूसरे में बदल सकते हैं (अनुक्रम के प्रत्येक आइटम को बदल सकते हैं, उदाहरण के लिए, फ़ाइल में एक पंक्ति कुछ डोमेन ऑब्जेक्ट में परिवर्तित करें) लेकिन ऐप का एक क्षेत्र दूसरे को प्रदान कर रहा है कर्सर है, इसलिए यह उपभोग करने के लिए एक हैंडल है फ़ाइलों को पढ़ने के ज्ञान के बीच में एक चरण में एक कदम इनपुट करें या जो भी परिवर्तन आप मध्य में लागू करते हैं। – helios

+0

आपके द्वारा प्रदान किए गए लिंक 'BufferedInputReader' और 'StringTokenizer' उपलब्ध नहीं हैं। – Root

6

यदि आप अपनी आवश्यकताओं को थोड़ा कम कर सकते हैं तो आप अपनी फ़ाइल द्वारा समर्थित java.lang.CharSequence को कार्यान्वित कर सकते हैं।

CharSequence many places in the JDK (ए स्ट्रिंग एक charSequence है) समर्थित है। तो यह रीडर-आधारित कार्यान्वयन का एक अच्छा विकल्प है।

1

आपको बड़े डेटा को निपटने के लिए अपने एल्गोरिदम की समीक्षा करनी होगी। आपको इस डेटा को चंक-बाय-चंक को संसाधित करना होगा, या स्मृति में डेटा संग्रहीत किए बिना यादृच्छिक फ़ाइल एक्सेस का उपयोग करना होगा। उदाहरण के लिए आप StringTokenizer या StreamTokenizer का उपयोग @Zombies के रूप में कर सकते हैं। आप पार्सर-लेक्सर तकनीकों को देख सकते हैं: जब पार्सर कुछ अभिव्यक्ति को पार करता है तो यह अगले लेक्सम (टोकन) को पढ़ने के लिए लेक्सर से पूछता है, लेकिन एक बार में पूरी इनपुट स्ट्रीम नहीं पढ़ता है।

4

अन्य लोगों ने एक ही समय में आपकी फ़ाइल के हिस्सों को पढ़ने और संसाधित करने का सुझाव दिया है। यदि संभव हो, तो उन तरीकों में से एक बेहतर होगा।

हालांकि, यदि यह संभव नहीं है और आप String को स्मृति में शुरू में स्मृति में लोड करने में सक्षम हैं, लेकिन बाद में यह इस स्ट्रिंग का विश्लेषण कर रहा है जो समस्याएं पैदा करता है, तो आप सबस्ट्रिंग का उपयोग करने में सक्षम हो सकते हैं। जावा में मूल char सरणी के शीर्ष पर एक उप-स्ट्रिंग मानचित्र और बेस Object और फिर प्रारंभ और लंबाई int पॉइंटर्स के लिए स्मृति लेता है।

इसलिए, जब आप स्ट्रिंग के एक हिस्से को, जिसे आपने अलग रखना चाहते हैं लगता है, की तरह कुछ का उपयोग करें:

String piece = largeString.substring(foundStart, foundEnd); 

इसके बजाय आप इस या कोड है कि आंतरिक रूप से करता है, तो स्मृति उपयोग में नाटकीय रूप से वृद्धि होगी, तो :

new String(largeString.substring(foundStart, foundEnd)); 

ध्यान दें कि आप यह बहुत ही कारण के लिए देखभाल के साथ String.substring() उपयोग करना चाहिए। आपके पास एक बहुत बड़ी स्ट्रिंग हो सकती है जिसमें से आप एक सबस्ट्रिंग लेते हैं और फिर मूल स्ट्रिंग के संदर्भ को छोड़ देते हैं। समस्या यह है कि सबस्ट्रिंग अभी भी मूल बड़े char सरणी का संदर्भ देता है। जीसी तब तक रिलीज नहीं करेगा जब तक कि सबस्ट्रिंग को भी हटा दिया न जाए। इस तरह के मामलों में, वास्तव में new String(...) का उपयोग करने के लिए उपयोगी है यह सुनिश्चित करने के लिए कि अप्रयुक्त बड़ी सरणी जीसी द्वारा छोड़ी जाएगी (यह उन कुछ मामलों में से एक है जहां आपको कभी भी new String(...) का उपयोग करना चाहिए)।

एक और तकनीक, यदि आप चारों ओर बहुत कम तारों की अपेक्षा करते हैं और इन्हें समान मान होने की संभावना है, लेकिन बाहरी स्रोत (फ़ाइल की तरह) से आते हैं, तो नई स्ट्रिंग बनाने के बाद .intern() का उपयोग करना है।

नोट: यह String के कार्यान्वयन पर निर्भर करता है जिसे आपको वास्तव में अवगत नहीं होना चाहिए, लेकिन बड़े अनुप्रयोगों के लिए अभ्यास में कभी-कभी आपको उस ज्ञान पर भरोसा करना पड़ता है। ध्यान रखें कि जावा के भविष्य के संस्करण इसे बदल सकते हैं (हालांकि संभावना नहीं है)।