Мне нужно обнаружить файлы, которые содержат мою строку. Размеры файлов могут быть больше 4 ГБ. Я не могу сделать это просто с помощью таких инструментов, как file_get_contents()
потому что он пытается поместить файл в оперативную память.
Как я могу это сделать? Используете стандартный PHP? Использует эластичный поиск или другой внешний поисковик?
Если у вас машина на основе Linux, вы можете использовать команду grep:
shell_exec( 'grep "text string to search" /path/to/file');
В качестве вывода у вас будут все строки, содержащие ваш текст.
Вот Вы можете найти простое руководство по использованию grep!
Если вам нужно найти все файлы, содержащие текст в каталоге, вы можете использовать
shell_exec( 'grep -rl "text string to search" /path/to/dir' );
r означает «рекурсивный», поэтому он будет выглядеть в каждом файле
л означает «показать имена файлов»
В результате у вас будут все имена файлов (по одному в строке).
file_get_contents
вернуть содержимое всего файла как переменную. В вашем случае это означает, что он попытается создать переменную 4 ГБ, которая исчерпает разрешенную память.
Попробуйте использовать Еореп а также fgets. Это позволит вам обрабатывать файлы небольшими порциями.
Попробуйте! 🙂
Вы можете использовать что-то вроде этого. Это не оптимизировано и не проверено вообще, и может иметь некоторую незамеченную ошибку мной, но вы должны понять:
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;
}