一个大文件查找缺失用户ID问题

问题描述:

有一堆文件,都是一堆ID,以前有些号码跳过了,没有使用,现在要挑出没有使用过的号码,ID大概有8亿多个,10亿开始,到21亿结尾。 从数据库读出数据存储时已按哈稀规则(id%257)存文件,每个文件大概有300万个。

很庆幸,21亿左右是32位机能处理的最大值。所以下面就径直使用mod和/了。如果超过32位,PHP还提供了BC Math系统函数,可以对任意长度数字的做四则运算。

    string bcmod ( string $left_operand , string $modulus ) 
echo bcmod('4', '2'); // 0
echo bcmod('2', '4'); // 2

最后看这个问题解决的代码:

    <?php
$mod = 0; //模:脚本中唯一变化参数
$array = array(); //实始化数组

//所有ID的最大值和最小值
$max_num = 2100000000;
$min_num = 1000000000;

$idea_max = $max_num;//初始化理想最大值
$idea_min = $min_num;//初始化理想最小值

//获取实际最大值
for ($i = $max_num; $i > $max_num-257; --$i) {
    if($mod == $i % 257)
        $idea_max = $i;
}
//获取实际最小值
for ($i = $min_num; $i < $min_num+257; ++$i) {
    if($mod == $i % 257)
        $idea_min = $i;
}
//打开文件,逐行读取
$handle = fopen("./auth".$mod.".txt", "r");
if ($handle) {
    $curr = $idea_min;//当前值设为理想最小值
    while (!feof($handle)) {
        //逐行读取
        $next = (int) fgets($handle, 4096);
        if($next < $min_num || $next < $idea_min) {
            //如果ID不在要求范围内,不做任何操作
            ;
        } else if ($next >= $idea_min && $next <= $idea_max) {
            //如果ID符合要求,继续循环判断:如果$next值大于$curr值
            while($next > $curr) {
                $array[] = $curr;
                $curr = $curr+257;
            }
            $curr = $next;
        } else {
            //其他情况一律不考虑
            ;
        }
    }
    fclose($handle);
}

write_num($array);

function write_num ($uid){
    global $mod;
    $fp = fopen('c'.$mod.'.txt','a');

    foreach($uid as $values) {
        fwrite($fp, $values."\r\n");
    }

    fclose($fp);
}