2010-08-27 10 views
14

मेरे पास एक स्क्रिप्ट है जो लाइन द्वारा बड़ी फाइलों को पार करती है। जब यह किसी त्रुटि से मुकाबला करता है जिसे वह संभाल नहीं सकता है, तो यह बंद हो जाता है, हमें अंतिम पंक्ति के बारे में सूचित करता है।fseek() लाइन से, बाइट्स नहीं?

क्या यह वास्तव में फ़ाइल में एक विशिष्ट पंक्ति की तलाश करने का सबसे अच्छा/एकमात्र तरीका है? (। fseek() मेरे मामले में प्रयोग करने योग्य नहीं है)

<?php 

for ($i = 0; $i < 100000; $i++) 
    fgets($fp); // just discard this 

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

उत्तर

30

एक आसान तरीका है एक फ़ाइल में एक विशिष्ट लाइन के लिए तलाश करने के लिए (SplFileObject वर्ग है, जो एक लाइन नंबर (seek()) या बाइट ऑफसेट करने की मांग का समर्थन करता है का उपयोग है fseek())।

$file = new SplFileObject('myfile.txt'); 
$file->seek(9999);  // Seek to line no. 10,000 
echo $file->current(); // Print contents of that line 

पृष्ठभूमि में, seek() सिर्फ तुम क्या अपने PHP कोड किया (सी कोड को छोड़कर) करता है।

+0

अच्छा! कुछ समय पहले इसने आया और इसका उपयोग करना शुरू कर दिया। – jasonbar

+0

इस मामले में, दी गई लाइन तक पहुंचने के लिए लाइन 1 - 9, 999 के माध्यम से चलने के बिना सीधे लाइन 10,000 पढ़ेगी? – Googlebot

+0

@ एली: नहीं, आपको कैसे लगता है कि यह जानता है कि लाइनें कहां से शुरू होती हैं? यह फ़ाइल के माध्यम से पढ़ता है। यदि आप सीधे एक लाइन की तलाश करना चाहते हैं तो अन्य विकल्प भी हैं, लेकिन फ़ाइल में कहां से शुरू होने वाली लाइनों का ट्रैक रखने के लिए संभावित जटिल सिस्टम शामिल हैं। – salathe

4

यदि आपके पास केवल लाइन नंबर है, तो लाइन खोजने का कोई अन्य तरीका नहीं है। फ़ाइलें लाइन आधारित नहीं हैं (या यहां तक ​​कि चरित्र आधारित), इसलिए फ़ाइल में किसी विशिष्ट पंक्ति पर कूदने का कोई तरीका नहीं है।

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

+0

हाँ, मुझे उतना ही लगा। किसी भी तरह मैंने सोचा कि एक अच्छा 'fseekbyline()' जो सी कोड के लिए सिर्फ एक रैपर था, मुझे बेहतर महसूस कर देगा। हे। – jasonbar

0

यदि मैं सही ढंग से समझता हूं, तो आप किसी त्रुटि को प्राप्त करने के बाद किसी विशिष्ट बिंदु पर विशिष्ट रेखा खोजना चाहते हैं। यदि ऐसा है, तो संभवतः आप "सूचित करें" के आधार पर, कहीं भी खराब लाइन की लाइन-संख्या को स्टोर या प्रिंट करते हैं।

जब तक आप वास्तव में मतलब है कि आप उपयोग नहीं कर सकते fseek() *, आप क्या कर सकते भी दुकान/फ़ाइल जहां बुरा लाइन शुरू होता है में प्रिंट की स्थिति में है। फिर आप fseek() कर सकते हैं।

* उस स्थिति में, fseekbyline() क्या अस्तित्व में होगा यदि यह अस्तित्व में है?

2

मैं जानता हूँ कि यह पोस्ट करने के लिए देर हो चुकी है लेकिन यह कुछ ppl मैं fseekbyline एक दिन की तरह एक समारोह था ... मदद कर सकते हैं

function GoToLine($handle,$line) 
{ 
    fseek($handle,0); // seek to 0 
    $i = 0; 
    $bufcarac = 0;      

    for($i = 1;$i<$line;$i++) 
    { 
    $ligne = fgets($handle); 
    $bufcarac += strlen($ligne); // in the end bufcarac will contains all caracters until the line 
    } 

    fseek($handle,$bufcarac); 
} 

कोई त्रुटि प्रणाली है, यदि आप लाइन < लिए जाना चाहता हूँ 1 या 203 लेकिन फ़ाइल खाली है ... आपको कुछ भी अच्छा नहीं मिलेगा।

ही यदि आप चाहते EOT से बाहर जाना

+0

जब तक PHP लूप के माध्यम से चला गया है, तो पॉइंटर होगा जहां आप वांछित थे।बस फेट्स ($ हैंडल) को कॉल करने के लिए लूप में डालने के लिए पर्याप्त है, और आप $ bufcarac और $ ligne चर में मेमोरी लोडिंग से बच सकते हैं। – Gregory

1
rewind($handle); 
while($i=0; $i<$desired_line; i++) 
    fgetcsv($handle, 1000, ",") 

यह मेरे लिए काम करते हुए मैं एक विशिष्ट लाइन के लिए मेरी स्क्रिप्ट में कई बार रिवाइंड करने के लिए की जरूरत है।

मुझे यकीन नहीं है कि यह स्मृति या गति खाती है, लेकिन यह चाल है।

+0

यह छोटा और बिंदु है। हालांकि fgetcsv किसी भी पाठ फ़ाइल की बजाय CSV फ़ाइलों के लिए विशिष्ट है। यह कम से कम मेरे लिए सहायक है। – Gregory

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