2013-07-25 13 views
5

मेरे पास एक बड़ी फाइल है जिसमें कई मिलियन लाइनें हैं और फ़ाइल से दूषित लाइनों को जांचने और निकालने की आवश्यकता है।बड़ी टेक्स्ट फ़ाइलों को पढ़ने और संशोधित करने के लिए 3-5 जीबी

मैंने लापरवाही से File.ReadAllLines की कोशिश की है लेकिन यह काम नहीं किया है। फिर मैंने मूल फ़ाइल से नीचे पढ़ने और एक नए लिखने के रूप में लाइनों को स्ट्रीम करने की कोशिश की। हालांकि यह नौकरी करता है, यह कई घंटों (5+) में ऐसा करता है। मैंने बफर का उपयोग करने के बारे में पढ़ा है जो एकमात्र विकल्प की तरह लगता है लेकिन मैं इस तरह लाइन अखंडता को कैसे बनाए रखूंगा?

समाधान: स्ट्रीमवाइटर थोड़ी देर के लिए बाहर चले गए। विभाजन के बजाय, गणना का उपयोग किया जाता है।

using (FileStream inputStream = File.OpenRead((localFileToProcess + ".txt"))) 
{ 
    using (StreamReader inputReader = new StreamReader(inputStream, System.Text.Encoding.GetEncoding(1254))) 
    { 
     using(StreamWriter writer=new StreamWriter(localFileToProcess,true,System.Text.Encoding.GetEncoding(1254))) 
     { 
      while (!inputReader.EndOfStream) 
      { 
      if ((tempLineValue = inputReader.ReadLine()).Count(c => c == ';') == 4) 
      { 
       writer.WriteLine(tempLineValue); 
      } 
      else 
       incrementCounter(); 
      } 
     } 
    } 
} 
+3

ध्यान दें कि स्प्लिट (';') एक सरणी आवंटित करता है और प्रत्येक पंक्ति के लिए स्मृति में 5 स्ट्रिंग बनाता है। यह एक कचरा कलेक्टर के लिए काम जोड़ता है। शायद आपको सिर्फ यह जांचना चाहिए कि आपकी लाइन में 4 अर्धविराम हैं? इसके अलावा प्रत्येक पुनरावृत्ति जिसे आप StreamWriter बना रहे/डिस्पोजेक्ट कर रहे हैं। शुरुआत में एक बनाने और ऑपरेशन के अंत में निपटान करना बेहतर नहीं है? – Artemix

+0

अच्छा बिंदु। मैं बदलाव करूंगा। – mechanicum

+0

एक स्ट्रिंग बिल्डर, प्रक्रिया में बैच पढ़ने के बारे में और फिर एक बार में लिखने के बारे में कैसे? – bhs

उत्तर

1

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

जब आपने केवल एक स्ट्रीमवाइटर का उपयोग करना शुरू किया, तो इसके आंतरिक लेखन बफर ने बड़े हिस्से में डिस्क को डेटा लिखना शुरू कर दिया। लिखने के लिए बंद/खोलने वाली फ़ाइल छोड़ने के साथ-साथ यह बहुत समय बचाता है। डिस्क I/O आमतौर पर एप्लिकेशन में सबसे धीमा हिस्सा होता है।

स्प्लिट (';') भी संभव गति प्रभाव था, लेकिन मुझे लगता है कि यह कम महत्वपूर्ण था। वैसे भी, स्ट्रिंग ऑपरेशंस को सी # में ध्यान से किया जाना चाहिए, क्योंकि तार अपरिवर्तनीय हैं और स्मृति में बहुत सारे कचरे का निर्माण कर सकते हैं। इसलिए, यदि आप 4 अर्धविरामों की जांच कर सकते हैं तो यह कॉल स्प्लिट (';') से हमेशा बेहतर होता है जो एक सरणी आवंटित करता है और (आपके मामले में) प्रत्येक पंक्ति के लिए स्मृति में 5 स्ट्रिंग बनाता है। जब अपरिवर्तनीय तारों का उपयोग करके बहुत सारे स्ट्रिंग ऑपरेशन किए जाते हैं तो यह किसी भी डिस्क I/O के बिना भी एप्लिकेशन प्रदर्शन को प्रभावित कर सकता है।

आपके मामले में स्ट्रिंगबिल्डर का उपयोग करने के लिए - मुझे नहीं लगता कि यह बहुत मदद करता है, क्योंकि StreamWriter में पहले से ही बफरिंग है।

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

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