быстрый поиск строк в PHP


У меня есть файл объемом 1,2 ГБ, содержащий строку в одну строку. Что мне нужно, так это выполнить поиск по всему файлу, чтобы найти позицию другой строки (в настоящее время у меня есть список строк для поиска). То, что я делаю сейчас, - это открываю большой файл и перемещаю указатель по блокам размером 4 Кб, затем перемещаю указатель на позиции X обратно в файл и получаю еще 4 КБ.

Моя проблема в том, что чем больше строка для поиска, тем больше времени ему требуется, чтобы ее получить.

Не могли бы вы дать мне несколько идей, чтобы оптимизировать скрипт, чтобы увеличить время поиска?

Это моя реализация:

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);
        }
    }

Заранее спасибо!

Author: Marc, 2010-06-10

2 answers

Почему бы не использовать 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);

Пример результата:

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);"
    ...
}

Каждый элемент состоит из смещения строки в байтах от начала файла и самой строки, разделенной двоеточием.
Поэтому после этого вам нужно заглянуть внутрь конкретной строки и добавить позицию к смещению строки. Т.е.:

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

Это означает, что "новое" вхождение найдено в 3408-м байте (3398 - позиция строки, а 10 - позиция "нового" внутри этой строки)

 9
Author: zerkms, 2010-06-10 01:09:14
$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
}

Однако размер файла довольно велик. вместо этого вы можете рассмотреть возможность хранения данных в базе данных. или, если вы абсолютно не можете, используйте решение grep, опубликованное здесь.

 1
Author: Sev, 2010-06-10 02:02:15