纯真ip数据文件php解析类
2011-03-21 11:46
309 查看
调用方式:
mixed QQWry::location(mixed $ip) — 获取ip中文地址(编码为gbk)
参数:
$ip:ip地址,可以是字符串(例:192.168.1.1),也可以是整数
返回值:数组或false,数组若为空,则未知地址,数组第一项为国家名,第二项为地区名
array QQWry::version() — 获取纯真ip数据文件版本
返回值:字符串(例:2010.10.20)
Demo地址:
http://demo.kilobug.com/ip/?ip=75.75.75.75
纯真ip数据文件的数据结构参考文档:
http://lumaqq.linuxsir.org/article/qqwry_format_detail.html
源码:
QQWry::singleton()->location('127.0.0.1'); 或 $qqwry = new QQWry(); $qqwry->location('127.0.0.1');
mixed QQWry::location(mixed $ip) — 获取ip中文地址(编码为gbk)
参数:
$ip:ip地址,可以是字符串(例:192.168.1.1),也可以是整数
返回值:数组或false,数组若为空,则未知地址,数组第一项为国家名,第二项为地区名
array QQWry::version() — 获取纯真ip数据文件版本
返回值:字符串(例:2010.10.20)
Demo地址:
http://demo.kilobug.com/ip/?ip=75.75.75.75
纯真ip数据文件的数据结构参考文档:
http://lumaqq.linuxsir.org/article/qqwry_format_detail.html
源码:
class QQWry{ private $version; private $fp; private $chr0; private $filepath = 'qqwry.dat'; private static $instance; public function __construct() { /* 打开文件 */ if( !($this->fp = @fopen($this->filepath, 'rb')) ) die('Can\'t open qqwry file'); $this->chr0 = chr(0); /* 获取索引区指针) */ $tmp = unpack('L2', fread($this->fp, 8)); $this->start = $tmp[1]; $this->tail = $tmp[2]+1; } public static function singleton() { if( !isset(self::$instance) ) { $clsname = __CLASS__; self::$instance = new $clsname(); } return self::$instance; } public function location( $ip ) { if( !is_numeric($ip) ) $ip = ip2long($ip); if( $ip === false ) return false; return $this->search( $this->longFormat($ip) ); } public function version() { if( !isset($this->version) ) { $this->version = $this->location(-1); preg_match_all('/\d+/', $this->version[1], $match); $this->version = implode('.', $match[0]); } return $this->version; } private function search( $ip ) { /* 索引条数 */ $ptail = ($this->tail - $this->start - 1) / 7; $pnums = intval($ptail / 2); $pstart = 0; /* 索引指针 */ $pointer = $this->tail - $pnums * 7 - 1; while( $pointer >= $this->start && $pointer < $this->tail ) { fseek($this->fp, $pointer); $index = unpack('L2', fread($this->fp, 7).$this->chr0); fseek($this->fp, $index[2]); $index[3] = unpack('L', fread($this->fp, 4)); $index[3] = $index[3][1]; $index[4] = $this->longFormat( $index[1] ); $index[5] = $this->longFormat( $index[3] ); if( $index[4] <= $ip && $ip <= $index[5] ) { // 找到 /* 获取地址 */ return $this->getLocation($index[2]); }elseif( $index[4] > $ip ) { // 前面 $ptail = $pnums; $pnums = $pstart + ceil(($pnums - $pstart) / 2); $pointer = $this->start + $pnums * 7; }else{ // 后面 $pstart = $pnums; $pnums += ceil(($ptail - $pnums) / 2); $pointer = $this->start + $pnums * 7; } $index = NULL; } return NULL; } private function getLocation( $offset ) { /* 地址数组,0位国家,1位地区,空则未知地区 */ $addr = array(); /* 标识符 */ $tmp = fread($this->fp, 1); $index = ord($tmp); /* 指针(4字节)+标识符(1字节) */ $offset += 5; if( $index == 1 ) { // 模式1 /* 获取跳转地址 */ $tmp = unpack('L', fread($this->fp, 3).$this->chr0); /* 开始跳转 */ fseek($this->fp, $offset = $tmp[1]); /* 读取地区 */ for($i = 0; $i < 2; ++$i) { /* 获取标识符 */ $tmp = fread($this->fp, 1); $index = ord($tmp); if( $index == 1 || $index == 2 ) { // 重定向 $tmp = unpack('L', fread($this->fp, 3).$this->chr0); fseek($this->fp, $tmp[1]); $addr[$i] = $this->getStr(); if( !isset($addr[$i]) ) unset($addr[$i]); $offset += 4; }elseif( $index == 0 ) { // 没有数据 break; }else { $addr[$i] = $tmp . $this->getStr(); if( !isset($addr[$i]) ) unset($addr[$i]); $offset += strlen($addr[$i])+1; } fseek($this->fp, $offset); } }elseif( $index == 2 ) { // 模式2 /* 获取跳转地址 */ $tmp = unpack('L', fread($this->fp, 3).$this->chr0); fseek($this->fp, $tmp[1]); $offset += 3; /* 读取地区 */ for($i = 0; $i < 2; ++$i) { $addr[$i] = $this->getStr(); if( !isset($addr[$i]) ) unset($addr[$i]); fseek($this->fp, $offset); } }else{ // 常规模式 $addr[0] = $tmp; /* 读取地区 */ for($i = 0; $i < 2; ++$i) { $addr[$i] .= $this->getStr(); if( !isset($addr[$i]) ) unset($addr[$i]); } } return $addr; } /* 长整数格式化 */ private function longFormat( $ip ) { return $ip + ($ip >= 0 ? -2147483647 : 2147483647); } private function getStr() { $str = ''; while( ($tmp = fread($this->fp, 1)) != $this->chr0 ) $str .= $tmp; return ord($str) < 32 || $str == ' CZ88.NET' ? NULL : $str; } public function __destruct() { if( $this->fp ) fclose($this->fp); } }
相关文章推荐
- php读取二进制流(C语言结构体struct数据文件)的深入解析
- 解析固定格式的文件数据 php脚本
- php读取二进制流(C语言结构体struct数据文件)的深入解析
- PHP文件数据传输用jQuery-ajax进行浏览器->服务器->数据文件->服务器->浏览器的数据传输($_POST,$_GET,json_encode(数组数据回应),json数据解析)
- 【函数库】PHP RXData(RPGXP数据文件) 解析库 V1.0
- java解析纯真IP数据库,查询IP,导出所有数据,插入oracle
- php读取二进制流(C语言结构体struct数据文件)的深入解析
- 通过读取QQ ip纯真dat数据文件,得到ip所在地
- 解决PHP读取纯真ip数据乱码问题
- 读取超大数据文件入库可能会用到的php.ini设置
- C#仪器数据文件解析-PDF文件
- 【开源.NET】轻量级内容管理框架Grissom.CMS(第三篇解析配置文件和数据以转换成 sql)
- PHP导出MySQL数据到Excel文件(fputcsv)
- 在FPGA的ROMIP核中导入由txt建立的coe数据文件并仿真
- 《项目经验》--后台一般处理程序向前台JS文件传递JSON,JS解析JSON,将数据显示在界面--显示在DropDownList 或 显示在动态创建的table中
- php中如何读取sqlite数据库文件的数据
- 【phpcms-v9】index.php文件分析-前台首页模板文件的解析过程分析
- PHP 常量、PHP 变量全解析(超全局变量、变量的8种数据类型等)
- PHP接收IOS post过来的json数据无法解析的问题
- PHP程序中的文件锁、互斥锁、读写锁使用技巧解析