2010-06-09 4 views
4

J'ai un fichier de 1,2 Go qui contient une chaîne d'une ligne. Ce dont j'ai besoin est de rechercher le fichier entier pour trouver la position d'une autre chaîne (actuellement j'ai une liste de chaînes à rechercher). La façon dont je le fais maintenant est d'ouvrir le gros fichier et de déplacer un pointeur à travers des blocs de 4Kb, puis de déplacer les positions du pointeur X dans le fichier et d'obtenir 4Kb de plus.recherche de chaîne de vitesse en PHP

Mon problème est qu'une plus grande chaîne de recherche, plus il prend de temps pour l'obtenir.

Pouvez-vous me donner quelques idées pour optimiser le script afin d'obtenir de meilleurs temps de recherche?

ceci est ma mise en œuvre:

function busca($inici){ 
     $limit = 4096; 

     $big_one = fopen('big_one.txt','r'); 
     $options = fopen('options.txt','r'); 

     while(!feof($options)){ 
      $search = trim(fgets($options)); 
      $retro = strlen($search);//maybe setting this position absolute? (like 12 or 15) 

      $punter = 0; 
      while(!feof($big_one)){ 
       $ara = fgets($big_one,$limit); 

       $pos = strpos($ara,$search); 
       $ok_pos = $pos + $punter; 

       if($pos !== false){ 
        echo "$pos - $punter - $search : $ok_pos <br>"; 
        break; 
       } 

       $punter += $limit - $retro; 
       fseek($big_one,$punter); 
      } 
      fseek($big_one,0); 
     } 
    } 

Merci à l'avance!

+0

Qu'est-ce qui se passe quand vous utilisez les strpos plaine() Fonctionne sur le fichier 1.2Go? – powtac

+0

J'ai trouvé un benchmark pour différentes méthodes de correspondance en PHP, mais strpos() est le plus rapide. http://www.hashbangcode.com/blog/fastest-way-match-string-php-200.html – powtac

+0

Quelle est la taille d'options.txt et à quoi cela ressemble-t-il? – 0scar

Répondre

8

Pourquoi ne pas utiliser exec + grep -b?

exec('grep "new" ext-all-debug.js -b', $result); 
// here we have looked for "new" substring entries in the extjs debug src file 
var_dump($result); 

résultat de l'échantillon:

array(1142) { 
    [0]=> string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:" 
    [1]=> string(54) "3910:var tpl = new Ext.DomHelper.createTemplate(html);" 
    ... 
} 

Chaque élément se compose de chaîne de décalage en octets du début du fichier et la ligne elle-même, séparés par deux points.
Donc, après cela, vous devez regarder à l'intérieur de la ligne particulière et ajouter la position à l'offset de ligne. À savoir:

[0]=> string(97) "3398: * insert new elements. Revisiting the example above, we could utilize templating this time:" 

cela signifie que « nouvelle » occurrence trouvée à l'octet 3408e (à l'intérieur de cette ligne 3398 est la position de la ligne et 10 est la position de la « nouvelle »)

+0

+1. Lorsque vous avez affaire à des fichiers de cette taille, il est préférable de laisser ce type de travail aux outils qui ont été construits pour le travail. –

+0

Je suis d'accord avec l'idée, mais j'ai besoin de la bonne façon de lancer grep.Quelle est la phrase correcte pour rechercher une chaîne dans un fichier avec grep? peut-il me rappeler juste la position du match? Merci – Marc

+0

@Marc: J'ai mis à jour la réponse – zerkms

1
$big_one = fopen('big_one.txt','r'); 
$options = fopen('options.txt','r'); 

while(!feof($options)) 
{ 
    $option = trim(fgets($options)); 
    $position = substr($big_one,$option); 

    if($position) 
    return $position; //exit loop 
} 

La taille du fichier est cependant assez importante. vous pourriez envisager de stocker les données dans une base de données à la place. ou si vous ne pouvez absolument pas, utilisez la solution grep affichée ici.

+0

peut-être l'insérer dans des blocs de 4 Ko par exemple? que foreach est pour diviser la chaîne? ou quoi? – Marc