我需要检测包含我的字符串的文件。文件大小可以大于4GB。我不能简单地使用像file_get_contents()
这样的工具,因为它试图将文件放入RAM中。
我该怎么做?使用标准PHP?使用elasticsearch或其他外部搜索引擎?
答案 0 :(得分:4)
如果您有基于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' );
r代表"递归",所以它会查找每个文件
l代表"显示文件名"
因此,您将拥有所有文件名(每行一个)。
答案 1 :(得分:2)
file_get_contents
将整个文件的内容作为变量返回。在你的情况下,这意味着它将尝试创建4GB变量,耗尽允许的内存。
尝试使用fopen和fgets。这将允许您以较小的块处理文件。
试一试! :)
答案 2 :(得分:2)
你可以使用这样的东西。这根本没有优化或测试,可能有一些未被注意到的bug,但你应该明白这个想法:
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;
}