2009-05-05 14 views
5

में एक पंक्ति मौजूद है, मैं सी # (.NET 2.0) का उपयोग कर रहा हूं, और मेरे पास काफी बड़ी टेक्स्ट फ़ाइल है (औसत पर ~ 1600 लाइनें) जिन्हें मुझे समय-समय पर जांचना है सुनिश्चित करें कि टेक्स्ट की एक निश्चित पंक्ति है।यह सुनिश्चित करने के लिए सबसे प्रभावी तरीका है कि एक सादा पाठ फ़ाइल

ऐसा करने का सबसे प्रभावी तरीका क्या है? क्या मुझे वास्तव में पूरी फाइल को हर बार स्मृति में लोड करना होगा?

क्या कोई फ़ाइल-सामग्री-खोज एपीआई है जिसका उपयोग मैं कर सकता था?

कोई मदद/सलाह के लिए धन्यवाद।

उत्तर

5

ठीक है, आप फ़ाइल को बदलते समय एक ईवेंट देने के लिए हमेशा FileSystemWatcher का उपयोग कर सकते हैं, इस तरह आप केवल मांग पर फ़ाइल स्कैन करते हैं।

+1

अच्छा विचार - हम इसे एक परियोजना में करते हैं और फिर भी मैं इसके बारे में भूल जाता हूं। –

+0

बहुत अच्छा! मुझे लगता है कि मैं शायद इस दृष्टिकोण का उपयोग करूंगा। –

+0

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

3

यदि पाठ की रेखा हमेशा समान होती जा रही है तो लाइन के पाठ से मेल खाने के लिए RegEx का उपयोग करना संभवतः स्ट्रिंग.इक्वाल्स() या == का उपयोग करके टेक्स्ट से मिलान करने के लिए फ़ाइल के माध्यम से लूपिंग से अधिक कुशल है।

यह कहा गया है कि, फ़ाइल में पाठ को खोलने और लाइनों को पढ़ने के साथ फ़ाइल में पाठ खोजने के लिए मुझे सी # में किसी भी तरह से पता नहीं है।

यह link सी # का उपयोग कर फ़ाइल में लाइनों से मिलान करने के लिए RegEx का उपयोग करने पर एक अच्छा ट्यूटोरियल है।

+0

इसके अलावा - यह शायद स्पष्ट है, लेकिन रेगेक्स का उपयोग करके लाइन को हमेशा एक जैसा नहीं होना चाहिए, इसे सिर्फ एक पहचानने योग्य पैटर्न का पालन करना होगा। –

+0

मुझे कुछ याद आ रहा है। प्रत्येक लाइन पर RegEx का उपयोग स्ट्रिंग से अधिक कुशल है। कंटेनर(), स्ट्रिंग .tartsWith(), या किसी अन्य अंतर्निहित स्ट्रिंग पार्सर्स? मेरे पास मिलान करने के लिए एक जटिल पैटर्न नहीं है। मैं एक सटीक स्ट्रिंग की तलाश में हूं। –

+0

मेरी धारणा पाठ के एक पैटर्न की तलाश में थी। –

1

आप सिर्फ इस तरह लाइनों पर पाश में सक्षम होना चाहिए:

String line; 
while ((line = file.ReadLine()) != null) 
{ 
    if (line matches regex blah) 
     return true; 
} 
return false; 

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

+0

धन्यवाद। यह भी मदद करता है। –

2

यह वास्तव में "कुशल" की आपकी परिभाषा पर निर्भर करता है।

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

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

यदि आप केवल कम से कम काम करने की तलाश में हैं तो क्या आप फ़ाइल के बारे में पहले ही जानते हैं? इसे कितनी बार अपडेट किया जाएगा? क्या प्रत्येक पंक्ति के पहले 10 अक्षर हमेशा समान होते हैं? यदि आपने पिछली बार 100 लाइनों को देखा तो क्या आपको उन पंक्तियों को फिर से स्कैन करने की आवश्यकता है? इनमें से कोई भी समय और स्मृति उपयोग दोनों के लिए बड़ी बचत कर सकता है।

दिन के अंत में कोई जादू बुलेट नहीं है, और फ़ाइल खोजने के लिए (सबसे खराब मामले में) ओ (एन) ऑपरेशन है।


क्षमा करें, बस इसे फिर से पढ़ें, और यह व्यंग्यात्मक के रूप में आ सकता है, और मेरा मतलब यह नहीं है। मेरा मतलब यह था कि एक क्षेत्र में आपके द्वारा किए गए किसी भी लाभ को कहीं और खोने की संभावना है और इन तरह की परिस्थितियों में "कुशल" एक बहुत संदिग्ध शब्द है।

+0

दुर्भाग्यपूर्ण बात यह है कि फ़ाइल * * भिन्न हो सकती है, लेकिन अधिकांश लगभग समान होंगे। और जिस लाइन की मैं तलाश कर रहा हूं उसका स्थान लगभग हर समय एक अलग जगह पर होगा। –

+1

ऐसे मामलों में यह मानना ​​फायदेमंद हो सकता है कि फ़ाइल लगभग समान है और इसे इस तरह संसाधित करें (उदाहरण के लिए खोज शुरू करें कि रेखा पहले कहां थी और विकिरण हो गई थी)।आप अपना सबसे खराब मामला धीमा कर सकते हैं, क्योंकि अब आप फ़ाइल को रैखिक रूप से नहीं पढ़ रहे हैं, लेकिन यदि आप शायद ही कभी उस बुरे मामले को हिट करते हैं तो समग्र प्रणाली मेरी दौड़ तेजी से चलती है। –

3

जब तक कि वे बहुत लंबी लाइनें न हों, आधुनिक कंप्यूटिंग शब्दों में 1600 लाइनें बहुत कुछ नहीं हैं!फ़ाइल IO को रनटाइम द्वारा संभाला जाएगा, और buffered किया जाएगा, और आश्चर्यजनक रूप से तेज़ होगा, और स्मृति पदचिह्न आश्चर्यजनक रूप से अपरिहार्य है।

बस लाइन से फ़ाइल लाइन पढ़ें, या System.IO.File.ReadAllLines() का उपयोग करें, और फिर देखें कि रेखा मौजूद है या नहीं। एक स्ट्रिंग के साथ एक पूरी लाइन तुलना का उपयोग कर।

यह आपकी बाधा नहीं होगी।

यदि आप बार-बार मतदान कर रहे हैं और/या नियमित रूप से नियमित अभिव्यक्तियों का उपयोग कर रहे हैं तो आपकी बाधा उत्पन्न हो सकती है। फ़ाइल को पार्स करने से बचने के लिए फ़ाइल सिस्टम वॉचर का उपयोग करना सबसे अच्छा है, अगर यह अपरिवर्तित है।)

1:

2
List<String> lines = System.IO.File.ReadAllLines(file).ToList() 
lines.Contains("foo"); 
+0

हाँ, समझने में आसान, मैं यह रखता हूं कि यह एक बाधा नहीं है, मेरा अपवित्र हो जाता है। पीएस: "सामग्री"? – Will

+0

ने इसे मेरे सिर के ऊपर से लिखा था। उस टाइपो के लिए खेद है। –

+0

ToList() .Net 3.5 असेंबली से आता है। मुझे 2.0 समाधान की आवश्यकता है। –

0

मैं यहाँ इस्तेमाल तकनीक के एक जोड़े गठबंधन होगा। फ़ाइल पर एक FileSystemWatcher सेट करें। झूठी सकारात्मक को रोकने के लिए आवश्यक फ़िल्टर सेट करें। आप फ़ाइल को अनावश्यक रूप से जांचना नहीं चाहते हैं।

2)। जब एफएसडब्ल्यू घटना को उठाता है, स्ट्रिंग फ़ाइलस्ट्रिंग = फ़ाइल। रीडअललाइन() का उपयोग करके सामग्री को पकड़ें।

3)। अपनी स्ट्रिंग के लिए मिलान खोजने के लिए एक सरल रेगेक्स का उपयोग करें।

4)। यदि मैच में -1 से अधिक इंडेक्स है, तो फ़ाइल में स्ट्रिंग होता है जो इंडेक्स में जो भी मान है।

आपने फ़ाइल लाइन को लाइन लाइन को पार्स करने से सफलतापूर्वक टाल दिया है, तो में संभावित रूप से बड़ी मात्रा में डेटा लोड किया गया है (हालांकि पाठ की 1600 पंक्तियां शायद ही बड़ी है) स्मृति में। जब स्ट्रिंग शाब्दिक दायरे से बाहर हो जाता है तो उसे कचरा कलेक्टर द्वारा पुनः दावा किया जाएगा।

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