zoukankan      html  css  js  c++  java
  • 通过本地文件数据库查询手机归属地

    <?php
    
    /**
     * 40W数据最多需要19次查找
     * 如果顺序查找的话26W数据最多要用9.28s
     * 二分查找法的话26W数据最多要用0.067s
     */
    define('KEY_SIZE', 12);                   //键值的大小
    
    class Mobile {
    
        private $idx_fp;
        private $dat_fp;
        private $idx_length;
        private $dat_length;
    
        public function __construct($filename = './mobile') {
            $idxfile = $filename . '.idx';
            $datfile = $filename . '.dat';
            $mode = file_exists($idxfile) ? 'r+b' : 'w+b';
            $this->idx_fp = fopen($idxfile, $mode);
            $this->dat_fp = fopen($datfile, $mode);
        }
    
        public function set($key, $value) {
            if ($this->_lock(true)) {
                $this->_setLength();
                $idxData = pack('L3', $key, $this->dat_length, strlen($value)); //索引的结构:键值+数据的数据偏移量+数据长度
                $this->_put($this->idx_fp, $this->idx_length, $idxData, KEY_SIZE);
                $this->_put($this->dat_fp, $this->dat_length, $value, strlen($value)); //写入数据
                $this->_unlock();
            } else {
                $this->_trigger_error('Could not lock this file !', E_USER_ERROR);
                return false;
            }
        }
    
        public function get($key) {
            $found = false;
            $this->_setLength();
            $start = 0;
            $end = ($this->idx_length-KEY_SIZE)/KEY_SIZE-1;
            while ($start <= $end) {
                $mid = ceil(($end + $start) / 2);
                $keyInfo = unpack('Lkey/Loffset/Llength', $this->_read($this->idx_fp, $mid*KEY_SIZE, KEY_SIZE));
                if ($keyInfo['key'] == $key) {
                    $found = true;
                    break;
                } elseif ($keyInfo['key'] < $key) {
                    $start=$mid+1;
                } else {
                    $end=$mid-1;
                }
            }
            if ($found) {
                return $this->_read($this->dat_fp, $keyInfo['offset'], $keyInfo['length']);
            }
            return false;
        }
    
        private function _seek($fp, $offset) {
            fseek($fp, $offset, SEEK_SET);
        }
    
        private function _put($fp, $offset, $data, $size) {
            $this->_seek($fp, $offset);
            fwrite($fp, $data, $size);
        }
    
        private function _read($fp, $offset, $size) {
            flock($fp, LOCK_SH);
            $this->_seek($fp, $offset);
            return fread($fp, $size);
            flock($fp, LOCK_UN);
        }
    
        private function _setLength() {
            clearstatcache();
            $info = fstat($this->idx_fp);
            $this->idx_length = $info['size'];
            $info = fstat($this->dat_fp);
            $this->dat_length = $info['size'];
        }
    
        /**
         * 锁定文件操作
         * @param type $isblock 是否堵塞
         */
        private function _lock($isblock) {
            $dFlock = flock($this->dat_fp, $isblock ? LOCK_EX : LOCK_EX + LOCK_NB);
            $iFlock = flock($this->idx_fp, $isblock ? LOCK_EX : LOCK_EX + LOCK_NB);
            return $dFlock && $iFlock;
        }
    
        private function _unlock() {
            $dFlock = flock($this->dat_fp, LOCK_UN);
            $iFlock = flock($this->idx_fp, LOCK_UN);
        }
    
        private function _trigger_error($error_msg, $error_type) {
            trigger_error($error_msg, $error_type);
        }
    
    }
    
    ?>

    这是初步代码,后期慢慢完善一下 演示地址:http://www.idoushuo.com/mobile/search.php

    最近又把做的手机归属地这个想了想,现在基于haseTable重写了一下,进行1w次查询,效率提升了一个量级(5.35524392128->0.413395023346),代码如下:

    <?php
    
    /*
      +------------------------------------------------------------------------------
      | datetime 2013-11-10  10:46:22
      +------------------------------------------------------------------------------
      | author baijm
      +------------------------------------------------------------------------------
      | version 1.0
      +------------------------------------------------------------------------------
     */
    
    class Mobile {
    
        private $header_padding = 20;
        private $file;
        private $handler;
    
        public function __construct($file) {
            $this->file = dirname(__FILE__) . '/' . $file . '.php';
            if (!file_exists($this->file)) {
                $this->_create();
            } else {
                $this->handler = fopen($this->file, 'r+b');
            }
        }
    
        public function set($key, $value) {
            clearstatcache();
            $len = filesize($this->file);
            $key = substr($key, 0, 7) - 1300000;
            $this->_put($this->header_padding + $key * 8, pack('VV', $len, strlen($value)));
            $data = $this->_put($len, $value);
            return true;
        }
    
        public function get($key) {
            $key = substr($key, 0, 7) - 1300000;
            $this->_seek($this->header_padding + $key * 8);
            list(, $offset, $len) = unpack('V2', fread($this->handler, 8));
            if (!$len) {
                return false;
            }
            $this->_seek($offset);
            return fread($this->handler, $len);
        }
    
        private function _create() {
            $this->handler = fopen($this->file, 'w+b') or $this->_trigger_error('Can not open the file' . realpath($this->file), E_USER_ERROR);
            $this->_put(0, '<?php exit(); ?>');
            return $this->_format();
        }
    
        private function _format() {
            if ($this->_lock(true)) {
                $this->_put($this->header_padding, str_repeat(pack('VV', 0x0000, 0x0000), 600000));
                return true;
            } else {
                $this->_trigger_error('Could not lock the file', E_USER_ERROR);
                return false;
            }
        }
    
        private function _put($offset, $data) {
            $this->_seek($offset);
            return fwrite($this->handler, $data);
        }
    
        private function _lock($block = true) {
            return flock($this->handler, $biock ? LOCK_EX : LOCK_EX + LOCK_NB);
        }
    
        private function _seek($offset) {
            fseek($this->handler, $offset, SEEK_SET);
        }
    
        private function _trigger_error($error_msg, $level) {
            trigger_error($error_msg, $level);
        }
    
    }
    
    ?>
  • 相关阅读:
    深度探索C++对象模型之第一章:关于对象之对象的差异
    深度探索C++对象模型之第一章:关于对象之关键词所引起的差异
    C++之constexpr
    STL之空间配置器
    10泛型算法
    C++之指针与数组区别
    数学 之 hdu 4861
    贪心 之 hdu 4864
    01背包(求前一个的最大价值-->求前K个的最大价值) 之 hdu 2639
    01背包(体积为负,改变区间) 之 poj 2184
  • 原文地址:https://www.cnblogs.com/bai-jimmy/p/3400971.html
Copyright © 2011-2022 走看看