索取Ip库,留言留下Email。
/*
二分法,查询IP文件
本文目的在于学习到fseek的使用方法和二分法原理
ip.csv文件格式
16908288,16908799,中国,福建省,未知
16908800,16909055,中国,北京市,北京市
16909312,16910335,中国,福建省,未知
1,2,3,4,5,6,7,8,9,10,11,12,13,14
3
mid = mid/2 = 7
$mid = $mid/2 = 4;
$mid = $mid/2 = 2;
$mid =
要求该文件,必须数字从小到大排列,否则无法采用二分法。
原理
1.得到文件大小703
2.折半对比IP数字大小,小于的,向前折半,大于的向后折半查找
header('Content-Type: text/html; charset=gbk'); $stime = time(); $ip = "124.58.180.5"; $address = readip($ip); echo $address; function readip($ip){ $ip_num = $ip_n = bindec(decbin(ip2long($ip))); echo $ip_num; $fname = 'ipfull.csv'; $fd = @fopen($fname, 'rb'); $size = filesize($fname);//得到文件大小,才好采用二分法 echo ' - size is : '; echo $size; echo '
'; $len = $size; $adress = ''; $sm = 0; $em = $size; $mid = ceil(($em - $sm)/2); $b = true; $ci = 0; //走的次数 while($b){ echo "$sm , $em , ".$mid.' - '; fseek($fd,$mid); $line = fread($fd, 80); $x = explode("\n",$line); $qline = $line; $line = ''; foreach($x as $k=>$v){ if(preg_match("/^\\d+,\\d+,.*?,.*?,.*?$/",$v)){ $line = $v; } } if($line==''){//最后的处理,直接命中 fseek($fd,$sm); $line = fread($fd,$size-$mid); $x = explode("\n",$line); foreach($x as $k=>$v){ if(preg_match("/^\\d{8,10},\\d{8,10},.*?,.*?,.*?/",$v)){ $line = $v; $arr = explode(',',$line); $start = intval($arr[0]); $end = intval($arr[1]); if($ip_num >= $start && $ip_num <= $end){ echo '命中'.$line; $address = $arr[2].$arr[3].$arr[4]; return $address; $b = false; break; } } } break; } $arr = explode(',',$line); $start = $arr[0]; $end = $arr[1]; if($ip_num < $start ){ echo '向前走'; $em = $mid; $mid = $sm + ceil(($em - $sm)/2); } if( $ip_num > $end){ echo '向后走'." # $start @ $end #"; $sm = $mid; $mid = $mid + ceil(($em - $sm)/2); } if($ip_num >= $start && $ip_num <= $end){ echo '命中'; $address = $arr[2].$arr[3].$arr[4]; $b = false; } echo ' -- '; echo $line; echo '
'; if($mid<2)$b = false; if($ci>100) $b = false;//说明没有找到 $ci++; } $etime = time(); $utime = $etime - $stime; echo $address; echo 'use time.'.$utime; return $address; }
经过测试这个方法,只需要1毫秒,即可查找到对应的IP地理位置