2016-03-04 3 views
0

Мне нужно обнаружить файлы, содержащие мою строку. Размер файлов может быть больше 4 ГБ. Я не могу этого сделать, просто используя такие инструменты, как file_get_contents(), потому что он пытается поместить файл в ОЗУ.Как найти текст в большом файле с помощью PHP?

Как это сделать? Использование стандартного PHP? Использование elasticsearch или другой внешней поисковой системы?

+0

Вы можете прочитать его строка за строкой, но это зависит от того, что эти conatain failes. Не могли бы вы рассказать нам больше о вашем файле (csv, xml, random text, 1line text ....) и о том, какую строку вы ищете? – Random

+0

Создайте цикл над содержимым файла .txt и используйте инструкции 'IF', чтобы отфильтровать то, что вы хотите видеть. – andre3wap

+0

Это похоже на лучший вариант: https://stackoverflow.com/questions/3686177/php-to-search-within-txt-file-and-echo-the-whole-line –

ответ

2

Если у вас есть машина на базе Linux, вы можете использовать команду Grep:

shell_exec('grep "text string to search" /path/to/file'); 

В выходе вы будете иметь все строки, содержащие текст.

here Вы можете найти простой учебник по использованию grep!

Если вам нужно найти все файлы, содержащие текст в каталоге, вы можете использовать

shell_exec('grep -rl "text string to search" /path/to/dir'); 

г означает «рекурсивный», так что это будет выглядеть в каждом файле

л обозначает " show filenames "

В результате у вас будут все имена файлов (по одному в строке).

+0

Спасибо! Это хорошее решение для Linux, и я бы использовал его для своих проектов, но теперь у меня есть задача запустить этот код в Linux и Windows. Лучшее решение, которое я знаю сейчас, состоит в том, чтобы разделить файл на части с помощью 'fopen',' fseek', 'fgets' и выполнить поиск в частичных файлах. –

+1

Я знаю, что это зависит от системы, поэтому не самая лучшая практика, но вы можете использовать эквивалентную для Windows таблицу findstr (https://technet.microsoft.com/en-us/library/bb490907.aspx), если вам интересно время (собственные функции конечно, быстрее, чем чтение строк в строку!) – Full

2

file_get_contents Возвращает содержимое всего файла в качестве переменной. В вашем случае это означает, что он попытается создать переменную 4 ГБ, которая исчерпывает допустимую память.

Пробуйте использовать fopen и fgets. Это позволит вам обрабатывать файлы в небольших кусках.

Попробуйте! :)

2

Вы можете использовать что-то вроде этого. Это не оптимизирован и протестирован на всех, и может иметь некоторую ошибку незамеченной со мной, но вы должны получить идею:

function findInFile($file_name, $search_string, $chunk_size=1024) { 
    // Because we are going to look back one chunk at a time, 
    // having $search_string more than twice of chunks will yield 
    // no result. 
    if (strlen($search_string) > 2 * $chunk_size) { 
     throw new \RuntimeException('Size of search string should not exceed size of chunk'); 
    } 
    $file = new \SplFileObject($file_name, 'r'); 
    $last_buffer = ''; 
    while (!$file->eof()) { 
     $chunk = $file->fread($chunk_size); 
     $buffer = $last_buffer . $chunk; 
     $position_in_buffer = strstr($buffer, $search_string); 
     if ($position_in_buffer !== false) { 
      // Return position of string in file 
      return 
       $file->ftell() - strlen($chunk) + $position_in_buffer 
      ; 
     } 
     $last_buffer = $chunk; 
    } 
    return null; 
}