2015-09-09 4 views
5

मैं PHP का उपयोग कर बाइनरी फ़ाइल में बाइट्स का एक विशिष्ट अनुक्रम खोजना चाहता हूं। मैंने हेक्साडेसिमल में इस अनुक्रम का प्रतिनिधित्व किया, ताकि बहुत सारे 0s और 1s टाइप से बच सकें। खोजने के लिए अनुक्रम 0x4749524f है।PHP में बाइनरी फ़ाइल में बाइट्स का अनुक्रम खोज रहे हैं?

$mysequence = "4749524f"; 
$f = fopen($filename, "r") or die("Unable to open file!"); 
while(!feof($f)){ 
    $seq = fread($f, 4); 
    if(bin2hex($seq) == $mysequence){ 
     echo "found!"; 
     break; 
    } 
    else if(!feof($f)) fseek($f, -3, SEEK_CUR); 
} 

क्या एल्गोरिथ्म करता है सरल है:: इस काम के समाधान मैं अब के लिए आया है

  1. पढ़ें 4 बाइट्स
  2. जांच करें कि वे कर रहे हैं अनुक्रम
  3. हैं के बराबर वे बराबर हैं -> मिला! निष्पादन रोको।
  4. वे बराबर नहीं कर रहे हैं और मैं फ़ाइल के अंत में नहीं कर रहा हूँ, तो वापस फ़ाइल में 3 बाइट्स जाने के लिए और दोहराने कदम 1.

क्यों मैं वापस जाने के लिए करते हैं 3 बाइट्स? क्योंकि अगर इस फ़ाइल की सामग्री है:

0000 4749 524f 0000 01b0 0013 

मैं जाना नहीं है, तो वापस 3 बाइट्स, मैं तीसरे पर दूसरे पर पहले यात्रा पर 0000 4749, 524f 0000, 01b0 0013 पढ़ा जाएगा और के रूप में आप देख सकते हैं मैं अनुक्रम याद किया।

समस्या: यह नरक की तरह धीमा है ... आवेदन को 50 एमबी तक बड़ी फ़ाइलों के साथ काम करना होगा, इसलिए यह हमेशा अनुक्रम को ढूंढने के लिए ले जाएगा।

क्या PHP में एक अनुकूलित फ़ंक्शन है जो नौकरी करेगा? क्या ऐसा करने के लिए कोई तेज (मेरा जैसे गूंगा नहीं) तरीका है?

+1

बाइट्स के लंबे सेट में पढ़ें, शायद 1 एम (या अधिक) की तरह कुछ। फिर स्मृति में खोजें। अगले 1 एमबाइट्स को पढ़ते समय, यह भी सुनिश्चित करना सुनिश्चित करें कि पहले सेट का अंतिम 3 सुई की शुरुआत थी या नहीं। –

+0

ठीक है, मैं इसे आजमा रहा हूँ! धन्यवाद। बीटीडब्ल्यू मैंने सोचा था कि फ़ाइल को पढ़ने के दौरान याद में कैश किया गया था ... क्या आपका मतलब है कि हर बार जब मैं फ़ंक्शन फ़्रेड चलाता हूं तो फ़ाइल सीधे हार्ड डिस्क से पढ़ी जाती है? –

+0

@AlbertoFontana यह एक ही दृष्टिकोण का सिर्फ एक संशोधन है, केवल बड़े हिस्सों में पढ़ा जाता है (मैं 4-8k का तर्क दूंगा) और फिर "चंक में ढूंढें" (बनाम "सटीक मिलान" बनाम)। स्प्लिट हिस्सों को आसानी से संभालने के लिए एक आसान तरीका है कि पीछे की तलाश भी हो, इसलिए कुछ बाइट्स द्वारा वास्तव में खंडों को ओवरलैप किया जाता है (यह नज़दीकी खोज अपेक्षाकृत कम होती है)। सिस्टम कॉल की कम संख्या यह है कि सबसे बड़ा प्रदर्शन अंतर क्या होगा। इसके अलावा पढ़ने के डेटा को हमेशा परिवर्तित करने के बजाय बाइट अनुक्रम में $ myverence को परिवर्तित करके थोड़ा और अधिक काम कम किया जा सकता है। – user2864740

उत्तर

1

डिस्क से पढ़ने से हमेशा लंबा समय लगता है। आप डिस्क कैशिंग पर भरोसा नहीं कर सकते हैं। यह एक ओएस चीज है। इसके बजाए, अपनी खुद की "कैशिंग" करें, जैसा कि यह था। बाइट्स के लंबे सेट में पढ़ें, शायद 1 एम (या अधिक) की तरह कुछ। यह डिस्क को कम करता है। फिर स्मृति में खोजें। अगले 1Mbytes को पढ़ने पर, पिछले सेट के अंतिम 3 बाइट्स को प्रीपेड करना सुनिश्चित करें। मिलने तक प्रत्येक सेट खोजें। आपके पढ़ने के वास्तविक आकार को राम उपयोग और डिस्क पढ़ने के बीच संतुलन होना आवश्यक होगा।

3

आपकी सभी $mysequence खोज के दौरान बदल नहीं रहा है, इसलिए आप hex2bin($mysequence) को एक बार कॉल कर सकते हैं और इसकी तुलना $seq से सीधे कर सकते हैं।

इसे वास्तव में तेज़ करने के लिए, आप बड़े बफर में स्ट्रिंग को पढ़ने और खोजने का प्रयास कर सकते हैं। बड़ा बफर => तेज़ खोज, लेकिन अधिक मेमोरी की आवश्यकता है। फास्ट कोड ड्राफ्ट, यह कैसा दिखना चाहिए:

$mysequence = "4749524f"; 
$searchBytes = hex2bin($mysequence); 
$crossing = 1 - length($searchBytes); // - (length - 1); see below 
$buf = ''; $buflen = 10000; 
$f = fopen($filename, "r") or die("Unable to open file!"); 
while(!feof($f)) 
{ 
    $seq .= fread($f, $buflen); 
    if(strpos($seq, $searchBytes) === false) // strict comparation here. zero can be returned! 
    { 
     // keep last n-1 bytes, because they can be beginning of required sequence 
     $seq = substr($seq, $crossing); 
    } 
    else 
    { 
     echo "found!"; 
     break; 
    } 
} 
unset($seq); // no need to keep this in memory any more 
+0

मुझे समझ में नहीं आया जब आपने कहा: "खोज के दौरान आपका $ seq बदल नहीं रहा है, इसलिए आप bin2hex() को एक बार कॉल कर सकते हैं।" बेशक $ seq में परिवर्तन, क्योंकि मैंने प्रत्येक लूप में एक नया अनुक्रम पढ़ा है ... क्या मैं गलत हूँ? –

+0

मेरी गलती। आप '' 'हेक्स 2bin ($ mysequence)' '' कॉल कर सकते हैं और $ seq के साथ तुलना कर सकते हैं। हर बार '' 'bin2hex''' कॉल किए बिना। –

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