如何读取两个大文件并比较内容

时间:2018-08-26 04:14:50

标签: php fopen

我想做的是读取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个小时,但尚未完成:/)。

我的问题是。有没有更好的方法来快速搜索大文件?

2 个答案:

答案 0 :(得分:1)

如果您要呼叫array_filter(),则无需呼叫array_unique()array_flip() -因为您不能在其中重复密钥,所以它将为您消除重复项相同级别的数组。

此外:

  1. array_unique()被认为比array_flip()慢(并且有时它比两个array_flip()要慢)
  2. array_filter()因杀死虚假/空/空/零位数据而享有声誉,因此,我提醒您不要使用其默认行为。
  3. array_flip()设置了非常快速的isset()检查。 isset()可能会胜过array_key_exists(),因为isset()不会检查null的值。
  4. 我正在向FILE_SKIP_EMPTY_LINES调用添加file()标志,以使您的查找数组可能更小。
  5. 调用大文件的每一行的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对数组进行排序,以了解更多关于出现的行最多,发生更少的行的信息,甚至可以进一步分析...