2011-12-18 17 views
7

में बड़ी फ़ाइल से एक विशिष्ट रेखा को पढ़ना क्या बड़ी फ़ाइल की विशिष्ट पंक्तियों को पढ़ने के लिए स्मृति के बिना लोड करने के लिए कोई तेज़ और मेमोरी प्रभावी तरीका है?पर्ल

मैंने एक पर्ल स्क्रिप्ट लिखी, जो कई कांटे चलाती है और मैं उन्हें फ़ाइल से विशिष्ट लाइनों को पढ़ना चाहता हूं।

पल इम एक बाहरी कमांड के प्रयोग पर:

sub getFileLine { 
    my ($filePath, $lineWanted) = @_; 
    $SIG{PIPE} = '_IGNORE_'; 
    open(my $fh, '-|:utf8', "tail -q -n +$lineWanted \"$filePath\" | head -n 1"); 
    my $line = <$fh>; 
    close $fh; 
    chomp($line); 
    return $line; 
} 

इसका तेजी से और यह काम करता है - लेकिन शायद वहाँ एक अधिक "पर्ल-ish" जिस तरह से, तेजी से और स्मृति यह एक के रूप में कुशल के रूप में?

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

मेरा लक्ष्य फोर्क प्रक्रिया को रखना है (इसलिए फोर्क्स चलने तक भी मुख्य प्रक्रिया) स्मृति जितनी कम हो सके उतनी कम उपयोग करें। Thats क्यों मैं पूरी फ़ाइल को स्मृति में लोड नहीं करना चाहता।

+2

बीटीडब्ल्यू, यह 'इग्नोर' है, न कि '_IGNORE_'। – ikegami

उत्तर

16

आगे जाने से पहले, यह समझना महत्वपूर्ण है कि कैसे fork काम करता है। जब आप fork एक प्रक्रिया करते हैं, तो ओएस माता-पिता और बाल प्रक्रियाओं की स्मृति को साझा करने के लिए copy-on-write अर्थशास्त्र का उपयोग करता है; माता-पिता और बच्चे के बीच अलग-अलग स्मृति की मात्रा को अलग से आवंटित करने की आवश्यकता होती है।

open my $fh, '<', $filePath or die "$filePath: $!"; 
my $line; 
while(<$fh>) { 
    if($. == $lineWanted) { 
     $line = $_; 
     last; 
    } 
} 

इस विशेष $. चर जो वर्तमान filehandle की लाइन संख्या रखती उपयोग करता है:

पर्ल में एक फ़ाइल की एक पंक्ति को पढ़ने के लिए, यहाँ एक आसान तरीका है।

4

Tie::File कोर मॉड्यूल पर एक नज़र डालें।

+0

मैंने सोचा था कि 'टाई :: फाइल' स्मृति-अक्षम था। ओपी अनुरोध कम स्मृति उपयोग नहीं किया था? – Zaid

+0

@Zaid यह वास्तव में मेमोरी-कुशल है; यह फ़ाइल की पूरी सामग्री को स्मृति में संग्रहीत नहीं करता है, केवल प्रत्येक पंक्ति के * ऑफसेट * की एक सूची। यह मुफ़्त नहीं है (यहां तक ​​कि केवल प्रत्येक ऑफ़सेट को रखने के लिए स्केलर प्रति पंक्ति कुछ जगह लेते हैं), लेकिन आमतौर पर बहु-सौ-मेगाबाइट फ़ाइलों को आसानी से संभालने के लिए पर्याप्त होता है। – hobbs

+0

@ हॉब्स: हाँ। मैंने तब से प्रलेखन को देखा है (टिप्पणी अब काफी पुरानी है), और यह स्पष्ट रूप से स्पष्ट करती है कि यह एक स्मृति हॉग नहीं है। – Zaid

0

आपको कांटा की आवश्यकता नहीं है। जैसा कि आप कल्पना कर सकते हैं, फ़ाइल से एक विशिष्ट रेखा को पढ़ना एक आम पर्याप्त ऑपरेशन है जो सीपीएएन पर 20k मॉड्यूल में से एक है।

File::ReadBackwards स्मृति-कुशल और तेज़ है।