搜索
首页后端开发PHP问题PHP如何在两个文件中找出相同的记录?

本篇文章给大家介绍一下PHP如何在两个文件中找出相同的记录的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

PHP如何在两个文件中找出相同的记录?

引言

给定a,b两个文件, 分别有x,y行数据, 其中(x, y均大于10亿), 机器内存限制100M,该如何找出其中相同的记录?fc430c7db1eecf4621f4fc8a5479f894

思路

  • 处理该问题的困难主要是无法将这海量数据一次性读内内存中.

  • 一次性读不进内存中,那么是否可以考虑多次呢?如果可以,那么多次读入要怎么计算相同的值呢?

  • 我们可以用分治思想, 大而化小。相同字符串的值hash过后是相等的, 那么我们可以考虑使用hash取模, 将记录分散到n个文件中。这个n怎么取呢? PHP 100M内存,数组大约可以存100w的数据, 那么按a,b记录都只有10亿行来算, n至少要大于200。

  • 此时有200个文件,相同的记录肯定在同一个文件中,并且每个文件都可以全部读进内存。那么可以依次找出这200个文件中各自相同的记录,然后输出到同一个文件中,得到的最终结果就是a, b两个文件中相同的记录。

  • 找一个小文件中相同的记录很简单了吧,将每行记录作为hash表的key, 统计key的出现次数>=2就可以了。

实操

10亿各文件太大了,实操浪费时间,达到实践目的即可。

问题规模缩小为:  1M内存限制, a, b各有10w行记录, 内存限制可以用PHP的ini_set('memory_limit', '1M');来限制。

生成测试文件

生成随机数用于填充文件:

/**
 * 生成随机数填充文件
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $filename 输出文件名
 * @param int $batch 按多少批次生成数据
 * @param int $batchSize 每批数据的大小
 */
function generate(string $filename, int $batch=1000, int $batchSize=10000)
{
    for ($i=0; $i<$batch; $i++) {
        $str = &#39;&#39;;
        for ($j=0; $j<$batchSize; $j++) {
            $str .= rand($batch, $batchSize) . PHP_EOL; // 生成随机数
        }
        file_put_contents($filename, $str, FILE_APPEND);  // 追加模式写入文件
    }
}

generate(&#39;a.txt&#39;, 10);
generate(&#39;b.txt&#39;, 10);

分割文件

  • a.txt, b.txt通过hash取模的方式分割到n个文件中.

/**
 * 用hash取模方式将文件分散到n个文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $filename 输入文件名
 * @param int $mod 按mod取模
 * @param string $dir 文件输出目录
 */
function spiltFile(string $filename, int $mod=20, string $dir=&#39;files&#39;)
{
    if (!is_dir($dir)){
        mkdir($dir);
    }

    $fp = fopen($filename, &#39;r&#39;);

    while (!feof($fp)){
        $line = fgets($fp);
        $n = crc32(hash(&#39;md5&#39;, $line)) % $mod; // hash取模
        $filepath = $dir . &#39;/&#39; . $n . &#39;.txt&#39;;  // 文件输出路径
        file_put_contents($filepath, $line, FILE_APPEND); // 追加模式写入文件
    }

    fclose($fp);
}

spiltFile(&#39;a.txt&#39;);
spiltFile(&#39;b.txt&#39;);
  • 执行splitFile函数, 得到如下图files目录的20个文件。

查找重复记录

现在需要查找20个文件中相同的记录, 其实也就是找一个文件中的相同记录,操作个20次。

  • 找一个文件中的相同记录:

/**
 * 查找一个文件中相同的记录输出到指定文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $inputFilename 输入文件路径
 * @param string $outputFilename 输出文件路径
 */
function search(string $inputFilename, $outputFilename=&#39;output.txt&#39;)
{
    $table = [];
    $fp = fopen($inputFilename, &#39;r&#39;);

    while (!feof($fp))
    {
        $line = fgets($fp);
        !isset($table[$line]) ? $table[$line] = 1 : $table[$line]++; // 未设置的值设1,否则自增
    }

    fclose($fp);

    foreach ($table as $line => $count)
    {
        if ($count >= 2){ // 出现大于2次的则是相同的记录,输出到指定文件中
            file_put_contents($outputFilename, $line, FILE_APPEND);
        }
    }
}
  • 找出所有文件相同记录:

/**
 * 从给定目录下文件中分别找出相同记录输出到指定文件中
 * Author: ClassmateLin
 * Email: classmatelin.site@gmail.com
 * Site: https://www.classmatelin.top
 * @param string $dirs 指定目录
 * @param string $outputFilename 输出文件路径
 */
function searchAll($dirs=&#39;files&#39;, $outputFilename=&#39;output.txt&#39;)
{
    $files = scandir($dirs);

    foreach ($files as $file)
    {
        $filepath = $dirs . &#39;/&#39; . $file;
        if (is_file($filepath)){
            search($filepath, $outputFilename);
        }
    }
}
  • 到这里已经解决了大文件处理的空间问题,那么时间问题该如何处理? 单机可通过利用CPU的多核心处理,不够的话通过多台服务器处理。

完整代码

推荐学习:php视频教程

以上是PHP如何在两个文件中找出相同的记录?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:segmentfault。如有侵权,请联系admin@php.cn删除

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

WebStorm Mac版

WebStorm Mac版

好用的JavaScript开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具