一个类似纯真IP数据库的存储和读取程序
2009-05-22 23:17
330 查看
一个类似纯真IP数据库的存储和读取程序 ,删除了国外的IP数据,国内只到省市一级 如:192.168.1.2 ,192.168.2.155 福建省 厦门市
write
<?php
error_reporting(E_ALL);
set_time_limit(0); //设置脚本运行时间,参数0为无限时
$link = mysql_connect('localhost','root','1');
mysql_select_db('ip',$link);
$fd = fopen("my.hb2008", "wb");
$datahead =pack('V',8);
$dataheadend =pack('V',465824);
fwrite($fd,$datahead);
fwrite($fd,$dataheadend);
$f=0;
$k =8; //索引区偏移
$i = 465830; ////记录区偏移
mysql_query("set names utf8");
$result = mysql_query("select * from wry order by fip ");
while ($row =mysql_fetch_object($result)) {
fseek($fd,$k);
$begin = $row->fip;
$endip = $row->eip;
$country = $row->country;
$area = $row->area;
$v_address = $country.' '.$area;
$length = strlen($v_address);
$v_begin = pack('V',floatval($begin));
$v_endip = pack('V',floatval($endip));
$v_offset = pack('V',floatval($i));
$v_length = pack('c',$length); //13字节
fwrite($fd,$v_begin);
fwrite($fd,$v_endip);
fwrite($fd,$v_offset);
fwrite($fd,$v_length);
fseek($fd,$i);
$f++;
fwrite($fd,$v_address);
$i = $i +$length;
$k = $k +13;
}
fclose($fd);
die('成功'.$f);
?>
read.php
<?php
/* $fp = fopen("a.hb2008", "r");
fseek($fp,80);
$data1 = fread($fp,4);
$p_data1 = unpack('Vbegin',$data1);
var_export($p_data1) ;
// $p_data2 = unpack('V',$data2);
//$count = ($p_data2 - $data1)/12;
//echo $count;
*/
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
class IpLocation {
/**
* QQWry.Dat文件指针
*
* @var resource
*/
var $fp;
/**
* ip数据文件地址
*
*@var string
*/
var $filename="IP/my.hb2008";
/**
* 第一条IP记录的偏移地址
*
* @var int
*/
var $firstip;
/**
* 最后一条IP记录的偏移地址
*
* @var int
*/
var $lastip;
/**
* IP记录的总条数(不包含版本信息记录)
*
* @var int
*/
var $totalip;
/**
* 返回读取的长整型数
*
* @access private
* @return int
*/
public function getlong() {
//将读取的little-endian编码的4个字节转化为长整型数
$result = unpack('Vlong', fread($this->fp, 4));
return $result['long'];
}
/**
* 返回压缩后可进行比较的IP地址
*
* @access private
* @param string $ip
* @return string
*/
public function packip($ip) {
// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,
// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
return pack('N', intval(ip2long($ip))); //TCP/IP各层协议将字节序定义为Big-Endian
}
/**
* 根据所给 IP 地址或域名返回所在地区信息
*
* @access public
* @param string $ip
* @return array
*/
public function getlocation($ip) {
if (!$this->fp) {
return false; // 如果数据文件没有被正确打开,则直接返回空
}
$location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址
$ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址
// 不合法的IP地址会被转化为255.255.255.255 big-endian
$beginip_validate = strrev(fread($this->fp, 4)) ;
if ($ip <$beginip_validate ) {
return false;
}else {
fseek($this->fp,$this->firstip);
}
// 二分查找法
$begin = 0; // 搜索的上边界
$end = $this->totalip; // 搜索的下边界
if (!($findip = $this->binary_classification($begin,$end,$ip))) {
return false;
}
fseek($this->fp, $findip);
$begin_ip_block = $this->getlong();
$end_ip_block = $this->getlong();
$address = $this->getlong();
$pack_length = fread($this->fp,1);
$length = unpack('c',$pack_length);
fseek($this->fp,$address);
$adr =fread($this->fp,$length[1]);
//获取查找到的IP地址位置信息
$location ['beginip'] = long2ip($begin_ip_block);
$location ['endip'] = long2ip($end_ip_block);
$location ['address'] = $adr;
return $location;
}
/**
* 构造函数,打开 文件并初始化类中的信息
*
* @param string $filename
* @return IpLocation
*/
public function __construct($file = null) {
if($file) {
$this->filename = $file;
} else{
$this->filename = dirname(__FILE__)."/".$this->filename;
}
if (($this->fp = @fopen($this->filename, 'rb')) !== false) {
$this->firstip = $this->getlong();
$this->lastip = $this->getlong();
$this->totalip = (($this->lastip - $this->firstip) / 13) ;
}
else
{
echo "false";
}
}
/**
* 析构函数,用于在页面执行结束后自动关闭打开的文件。
*
*/
public function __destruct () {
if ($this->fp) {
fclose($this->fp);
}
$this->fp = null;
}
/**
* 二分法
*
*/
public function binary_classifica
ad88
tion ($begin,$end,$ip)
{
$findip = null;
while ($begin <= $end) { // 当下边界小于上边界时,查找失败
$middle = floor(($begin + $end) / 2); // 计算近似中间记录
fseek($this->fp, $this->firstip + ($middle-1) * 13);
$beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址 =>变成大端
// strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式big-endian(大端) 以便用于比较,后面相同。
if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时
$end = $middle - 1; // 将搜索的下边界修改为中间记录减一
}else {
$endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址
if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时
$begin = $middle + 1; // 将搜索的上边界修改为中间记录加一
}else { // 用户的IP在中间记录的IP范围内时
$findip = $this->firstip + $middle * 13; //var_dump($findip);
return $findip;
break; // 则表示找到结果,退出循环
}
}
}
}
}
var_dump( long2ip(974170117));;
$a = new IpLocation;
$b =$a->getlocation("58.16.168.5");
var_export($b);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did nothing in $time seconds/n";
?>
write
<?php
error_reporting(E_ALL);
set_time_limit(0); //设置脚本运行时间,参数0为无限时
$link = mysql_connect('localhost','root','1');
mysql_select_db('ip',$link);
$fd = fopen("my.hb2008", "wb");
$datahead =pack('V',8);
$dataheadend =pack('V',465824);
fwrite($fd,$datahead);
fwrite($fd,$dataheadend);
$f=0;
$k =8; //索引区偏移
$i = 465830; ////记录区偏移
mysql_query("set names utf8");
$result = mysql_query("select * from wry order by fip ");
while ($row =mysql_fetch_object($result)) {
fseek($fd,$k);
$begin = $row->fip;
$endip = $row->eip;
$country = $row->country;
$area = $row->area;
$v_address = $country.' '.$area;
$length = strlen($v_address);
$v_begin = pack('V',floatval($begin));
$v_endip = pack('V',floatval($endip));
$v_offset = pack('V',floatval($i));
$v_length = pack('c',$length); //13字节
fwrite($fd,$v_begin);
fwrite($fd,$v_endip);
fwrite($fd,$v_offset);
fwrite($fd,$v_length);
fseek($fd,$i);
$f++;
fwrite($fd,$v_address);
$i = $i +$length;
$k = $k +13;
}
fclose($fd);
die('成功'.$f);
?>
read.php
<?php
/* $fp = fopen("a.hb2008", "r");
fseek($fp,80);
$data1 = fread($fp,4);
$p_data1 = unpack('Vbegin',$data1);
var_export($p_data1) ;
// $p_data2 = unpack('V',$data2);
//$count = ($p_data2 - $data1)/12;
//echo $count;
*/
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
$time_start = microtime_float();
class IpLocation {
/**
* QQWry.Dat文件指针
*
* @var resource
*/
var $fp;
/**
* ip数据文件地址
*
*@var string
*/
var $filename="IP/my.hb2008";
/**
* 第一条IP记录的偏移地址
*
* @var int
*/
var $firstip;
/**
* 最后一条IP记录的偏移地址
*
* @var int
*/
var $lastip;
/**
* IP记录的总条数(不包含版本信息记录)
*
* @var int
*/
var $totalip;
/**
* 返回读取的长整型数
*
* @access private
* @return int
*/
public function getlong() {
//将读取的little-endian编码的4个字节转化为长整型数
$result = unpack('Vlong', fread($this->fp, 4));
return $result['long'];
}
/**
* 返回压缩后可进行比较的IP地址
*
* @access private
* @param string $ip
* @return string
*/
public function packip($ip) {
// 将IP地址转化为长整型数,如果在PHP5中,IP地址错误,则返回False,
// 这时intval将Flase转化为整数-1,之后压缩成big-endian编码的字符串
return pack('N', intval(ip2long($ip))); //TCP/IP各层协议将字节序定义为Big-Endian
}
/**
* 根据所给 IP 地址或域名返回所在地区信息
*
* @access public
* @param string $ip
* @return array
*/
public function getlocation($ip) {
if (!$this->fp) {
return false; // 如果数据文件没有被正确打开,则直接返回空
}
$location['ip'] = gethostbyname($ip); // 将输入的域名转化为IP地址
$ip = $this->packip($location['ip']); // 将输入的IP地址转化为可比较的IP地址
// 不合法的IP地址会被转化为255.255.255.255 big-endian
$beginip_validate = strrev(fread($this->fp, 4)) ;
if ($ip <$beginip_validate ) {
return false;
}else {
fseek($this->fp,$this->firstip);
}
// 二分查找法
$begin = 0; // 搜索的上边界
$end = $this->totalip; // 搜索的下边界
if (!($findip = $this->binary_classification($begin,$end,$ip))) {
return false;
}
fseek($this->fp, $findip);
$begin_ip_block = $this->getlong();
$end_ip_block = $this->getlong();
$address = $this->getlong();
$pack_length = fread($this->fp,1);
$length = unpack('c',$pack_length);
fseek($this->fp,$address);
$adr =fread($this->fp,$length[1]);
//获取查找到的IP地址位置信息
$location ['beginip'] = long2ip($begin_ip_block);
$location ['endip'] = long2ip($end_ip_block);
$location ['address'] = $adr;
return $location;
}
/**
* 构造函数,打开 文件并初始化类中的信息
*
* @param string $filename
* @return IpLocation
*/
public function __construct($file = null) {
if($file) {
$this->filename = $file;
} else{
$this->filename = dirname(__FILE__)."/".$this->filename;
}
if (($this->fp = @fopen($this->filename, 'rb')) !== false) {
$this->firstip = $this->getlong();
$this->lastip = $this->getlong();
$this->totalip = (($this->lastip - $this->firstip) / 13) ;
}
else
{
echo "false";
}
}
/**
* 析构函数,用于在页面执行结束后自动关闭打开的文件。
*
*/
public function __destruct () {
if ($this->fp) {
fclose($this->fp);
}
$this->fp = null;
}
/**
* 二分法
*
*/
public function binary_classifica
ad88
tion ($begin,$end,$ip)
{
$findip = null;
while ($begin <= $end) { // 当下边界小于上边界时,查找失败
$middle = floor(($begin + $end) / 2); // 计算近似中间记录
fseek($this->fp, $this->firstip + ($middle-1) * 13);
$beginip = strrev(fread($this->fp, 4)); // 获取中间记录的开始IP地址 =>变成大端
// strrev函数在这里的作用是将little-endian的压缩IP地址转化为big-endian的格式big-endian(大端) 以便用于比较,后面相同。
if ($ip < $beginip) { // 用户的IP小于中间记录的开始IP地址时
$end = $middle - 1; // 将搜索的下边界修改为中间记录减一
}else {
$endip = strrev(fread($this->fp, 4)); // 获取中间记录的结束IP地址
if ($ip > $endip) { // 用户的IP大于中间记录的结束IP地址时
$begin = $middle + 1; // 将搜索的上边界修改为中间记录加一
}else { // 用户的IP在中间记录的IP范围内时
$findip = $this->firstip + $middle * 13; //var_dump($findip);
return $findip;
break; // 则表示找到结果,退出循环
}
}
}
}
}
var_dump( long2ip(974170117));;
$a = new IpLocation;
$b =$a->getlocation("58.16.168.5");
var_export($b);
$time_end = microtime_float();
$time = $time_end - $time_start;
echo "Did nothing in $time seconds/n";
?>
相关文章推荐
- 读取纯真IP数据库QQwry.dat的java版程序报数组越界异常问题
- 读取纯真IP数据库QQwry.dat的java版程序报数组越界异常问题 .22
- 从纯真ip数据库读取ip地址对应的地理信息的程序
- 编写一个程序,它从标准输入读取C源代码,并验证所有的花括号都正确的成对出现
- 编写一个函数,返回一个int数组中存储的最大数值,并在一个简单的程序中测试这个函数。(有缺陷)
- C#读取纯真IP数据库
- 编写一个程序,该程序读取整数,直到输入0为止,输入终止后,报告输出偶数个数,偶数平均数,奇数个数,奇数平均数
- (1) 写一个 Properties 格式的配置文件,配置类的完整名称。 * (2) 写一个程序,读取这个 Properties 配置文件,获得类的完整名称并加载这个类,用 反射 的方式运行
- 【C语言】编写一个程序,它从标准输入读取C源代码,并验证所有花括号都正确的成对出现(修改)
- 一个问题:物理内存有限的情况下,多个进程存在时,每个进程实际分配的物理内存有多少?(如果某程序申请了很大的动态存储空间)
- C语言 编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- C语言 编写一个程序,它从标准输入读取C源代码,并验证所有的花括号都正确的成对出现。
- Discuz 5.0 中读取纯真IP数据库函数分析
- 编写一个程序,它从标准输入读取C源代码,并验证所有的花括号都正确的成对出现
- 在xcode中写一个unix文件读取的程序
- 短信一次发送字节140个,如果超过140字节就会分为两条。这时如果第140个字节是中文的前半,那么第一条短信应该发送139字节。设计一个程序,读取原始信息,可以根据长度自动拆分信息转换为多条短信
- php读取纯真ip数据库使用示例
- C++中读取一个txt数值的程序
- 编写一个程序,首先用opendir函数打开用户指定的目录,然后调用readdir函数读取该目录内容
- 自己写了一个类似百度空间自动保存草稿的程序 php+jquery