Chinaunix首页 | 论坛 | 博客
  • 博客访问: 73010
  • 博文数量: 46
  • 博客积分: 1145
  • 博客等级: 少尉
  • 技术积分: 640
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-01 14:40
文章分类
文章存档

2017年(1)

2014年(4)

2013年(9)

2012年(32)

我的朋友

分类:

2012-07-20 11:51:38

/*
二分法,查询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地理位置
首发于http://java-er.com/blog/php-ip-address/
阅读(256) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~