在文件中查找字符串的最快方法是什么?

3

假设我有一个大文件。该文件是一个IP列表,每个IP都在新的一行上,就像这样:

123.123.123.123
123.123.123.124
123.123.123.125
etc...

我可以这样做:
$file = file_get_contents($src);    
if (substr_count($file,'myip'))
    echo 'FOUND';

或者使用类似数组的方式:

$file = file($src,FILE_IGNORE_NEW_LINES);
if (in_array('myip',$file))
    echo 'FOUND';

但我认为有第三种选择可能更快。
逐行解析文件,并在找到字符串后停止读取。

就像这样:

$file = fopen($src,'r');
while(!feof($file)) { 
    $ip = fgets($file);
    if ($ip == $myIP) {
        die('Found');
    }   
}
fclose($file);

我的问题是:你认为还有其他更好的方法吗?

就性能而言,你认为哪个代码更快?

非常感谢大家。


4
可以使用类似于grepfind这样的命令行工具吗? - Pekka
如果你认为它更快,我相信我可以使用它。 - anon
grep 可能比你自己编写的任何东西都要快。 - CodesInChaos
前两种方法将整个文件映射到内存中(或者至少试图这样做)- 这对于大文件来说不起作用,如果搜索字符串靠近文件顶部,则效率也不高。第三种方法将控制流程放入您的代码中 - 因此,它会相当慢,因为它在每个操作中处理PHP源代码。就像peka所说的那样 - 如果(grep $myIP $file)die('found'); - symcbean
(上面的grep命令周围应该有反引号) - symcbean
显示剩余6条评论
3个回答

1

如果可以的话,考虑使用 grep 或者 find。它可能比 PHP 更快,更重要的是,占用更少的内存。


Pekka,我相信你不想做一个测试用例吧?哈哈 - dynamic
pekka:我相信grep不可能比我的第三个解决方案更快。因为grep会一直搜索到文件结尾,而不会在第一次出现时停止。 - dynamic
@yes grep有相应的参数。请参考http://unixhelp.ed.ac.uk/CGI/man-cgi?fgrep中的`-l`。 - Pekka
我会接受这个,但我认为这不是最好的情况,因为如果你需要大量搜索,分叉例程的开销将会产生影响。 - dynamic
@是的,我认为这并不一定需要——这取决于您的文件有多大,有多少个以及您将使用一个调用处理多少个文件。 - Pekka

0

假设在某种语言中完成这个任务是必要的,那么修改你的逐行代码可能是最好的选择,这样你就不会获取比你需要的更多的数据。

$file = fopen($src,'r');
while(!feof($file)) { 
    $ip = fgets($file);
    if ($ip == $myIP) {
        echo 'FOUND!';
        break; // dieing here won't close the file
    }   
}

fclose($file);

你知道在 PHP 脚本结束时所有资源都会自动释放吗? - dynamic
2
如果有人将在这里看到的代码结构并在另一种语言(如C)中使用它,可能不会起到相同的作用。向读者传授正确的约定并不是一个坏主意。 - Christopher Armstrong

0
如果您能保持文件排序,那么执行二分查找将会表现良好。
然而,对文件进行排序需要一些时间,因此如果您正在进行大量的插入/删除操作,它可能不是非常有效。

嗯,这可能很有趣...无论如何,我从不删除项目,只是插入(我会在一定时间间隔内删除整个文件)。 - dynamic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接