我想做的是读取5.6GB的大文件,大约有6亿行,第二个是读取16MB的,有200万行。
我要检查这两个文件中的重复行。
$wordlist = array_unique(array_filter(file('small.txt', FILE_IGNORE_NEW_LINES)));
$duplicate = array();
if($file = fopen('big.txt', 'r')){
while(!feof($file)){
$lines = rtrim(fgets($file));
if(in_array($lines, $wordlist)){
echo $lines." : exists.\n";
}
}
fclose($file);
}
但这要花很多时间才能完成(它已经运行了6个小时,但尚未完成:/)。
我的问题是。有没有更好的方法来快速搜索大文件?
答案 0 :(得分:1)
如果您要呼叫array_filter()
,则无需呼叫array_unique()
或array_flip()
-因为您不能在其中重复密钥,所以它将为您消除重复项相同级别的数组。
此外:
array_unique()
被认为比array_flip()
慢(并且有时它比两个array_flip()
要慢)array_filter()
因杀死虚假/空/空/零位数据而享有声誉,因此,我提醒您不要使用其默认行为。array_flip()
设置了非常快速的isset()
检查。 isset()
可能会胜过array_key_exists()
,因为isset()
不会检查null
的值。FILE_SKIP_EMPTY_LINES
调用添加file()
标志,以使您的查找数组可能更小。rtrim()
可能也会造成一些拖累。您知道两个文件中的换行符是否一致吗?如果您可以安全地从rtrim()
调用中删除FILE_IGNORE_NEW_LINES
标志,那么将为您节省file()
的六亿次调用。另外,如果您知道跟随big.txt行的换行符(例如\n
?或\r\n
?),则可以将特定的换行符附加到{{ 1}}键-这意味着准备小文件的数据与大文件的每一行。未经测试的代码:
$lookup
答案 1 :(得分:0)
我认为
$wordlist=array_flip(array_unique(array_filter(file('small.txt', FILE_IGNORE_NEW_LINES))));
您在代码中实际使用的会减慢它的速度。一次构建单词表并自己动摇可能会更好:
if($file1 = fopen('big.txt', 'r')){
if($file = fopen('small.txt', 'r')){
while(!feof($file)){
$line=trim(fgets($file));
if(!isset($wordlist[$line])&&!ctype_space($line)&&!empty($line)){
$wordlist[$line]=0;
}
}
fclose($file);
}
while(!feof($file1)){
$line1 = trim(fgets($file1));
if(isset($wordlist[$line1]))
$wordlist[$line1]++;
}
fclose($file1);
}
在此步骤中,变量$ wordlist包含small.txt文件中所有行的列表以及big.txt文件中每行的出现次数。 您可以使用类似的数组或对其进行过滤以删除空行。您也可以使用uasort对数组进行排序,以了解更多关于出现的行最多,发生更少的行的信息,甚至可以进一步分析...