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

How to read two big files and compare contents

我想做的是读取大文件 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 个小时开始,但还没有完成:/)。

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

我觉得

 $wordlist=array_flip(array_unique(array_filter(file('small.txt', FILE_IGNORE_NEW_LINES))));

你实际在你的代码中使用它,速度变慢 it.It 构建一次单词列表可能会更好:

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 文件中每一行的出现次数。 您可以像那样使用数组或过滤它以删除 null lines.You 也可以使用 uasort 对数组进行排序以了解更多关于哪些行出现次数最多以及哪些行出现次数较少的信息,您甚至可以进一步分析。 ..

如果您要调用 array_flip(),则不需要调用 array_filter()array_unique() -- 它会为您消除重复项,因为您不能重复同级数组中的键。

此外:

  1. array_unique() 据说比 array_flip() 慢(有时它比两个 array_flip() 慢)
  2. array_filter() 因杀死 falsey/empty/null/zero-ish 数据而声名狼藉,因此我会提醒您不要使用其默认行为。
  3. array_flip() 设置非常快速的 isset() 检查。 isset() 可能会优于 array_key_exists(),因为 isset() 不检查 null 值。
  4. 我正在将 FILE_SKIP_EMPTY_LINES 标志添加到 file() 调用中,这样您的查找数组可能会更小。
  5. 对大文件的每一行调用 rtrim(),也可能造成一些拖累。您知道两个文件中的换行符是否一致吗?如果您可以安全地从 file() 调用中删除 FILE_IGNORE_NEW_LINES 标志,则可以节省 6 亿次 rtrim() 调用。或者,如果您 知道 尾随 big.txt 行的换行符(例如 \n? 或 \r\n?),您可以附加特定的换行符) 到 $lookup 键——这意味着准备小文件的数据与大文件的每一行。

未经测试的代码:

$lookup = array_flip(file('small.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES));
if($file = fopen('big.txt', 'r')){
    while(!feof($file)){
        $line = rtrim(fgets($file));
        if (isset($lookup[$line])) {
            echo "$lines : exists.\n";
        }
    }
    fclose($file);
}