最新手机号段归属地数据库 高性能dat解析[通俗易懂]

最新手机号段归属地数据库 高性能dat解析[通俗易懂]最新手机号段数据库2019-12-01441831条记录号码归属地数据库全面准确规范字段包括省份城市运营商邮编区号等信息,对于数据分析、号码归属地查询等非常有帮助名称:手机号码归属地查询dat高效率查询内存优化版压缩:原版txt为22M,生成这种dat结构为2.66M性能:每秒解析300万+号段或者号码,简洁高效环境:CPU…

大家好,又见面了,我是你们的朋友全栈君。

 

最新 手机号段数据库  2020-08-15 458461条记录  号码归属地数据库  全面  准确  规范 
字段包括 省份 城市 运营商 邮编 区号 等信息,对于数据分析、号码归属地查询等非常有帮助

最新手机号段归属地数据库 高性能dat解析[通俗易懂]

名称:手机号码归属地查询 dat高效率查询  内存优化版
压缩:原版txt为22M,生成这种dat结构为2.66M 
性能:每秒解析300万+号段或者号码,简洁高效 
环境:CPU i7-7700K +内存16GB

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

namespace qqzeng_phone_dat
{

    public class PhoneSearchFast
    {
        private static readonly Lazy<PhoneSearchFast> lazy = new Lazy<PhoneSearchFast>(() => new PhoneSearchFast());
        public static PhoneSearchFast Instance { get { return lazy.Value; } }
        private PhoneSearchFast()
        {
            LoadDat();
            Watch();
        }

        private string datPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"qqzeng-phone.dat");
        private DateTime lastRead = DateTime.MinValue;
        private long[,] prefmap = new long[200, 2];//  000-199


        private long[,] phonemap;

        private byte[] data;

        private long[] phoneArr;
        private string[] addrArr;
        private string[] ispArr;

        /// <summary>
        /// 初始化二进制dat数据
        /// </summary>
        /// <param name="dataPath"></param>
        /// 


        private void LoadDat()
        {
            data = File.ReadAllBytes(datPath);

            long PrefSize = BytesToLong(data[0], data[1], data[2], data[3]);
            long RecordSize = BytesToLong(data[4], data[5], data[6], data[7]);

            long descLength = BytesToLong(data[8], data[9], data[10], data[11]);
            long ispLength = BytesToLong(data[12], data[13], data[14], data[15]);

            //内容数组
            int descOffset = (int)(16 + PrefSize * 9 + RecordSize * 7);
            string descString = Encoding.UTF8.GetString(data, descOffset, (int)descLength);
            addrArr = descString.Split('&');

            //运营商数组
            int ispOffset = (int)(16 + PrefSize * 9 + RecordSize * 7 + descLength);
            string ispString = Encoding.UTF8.GetString(data, ispOffset, (int)ispLength);
            ispArr = ispString.Split('&');



            //前缀区
            int m = 0;
            for (var k = 0; k < PrefSize; k++)
            {
                int i = k * 9 + 16;
                int n = data[i];
                prefmap[n, 0] = BytesToLong(data[i + 1], data[i + 2], data[i + 3], data[i + 4]);
                prefmap[n, 1] = BytesToLong(data[i + 5], data[i + 6], data[i + 7], data[i + 8]);
                if (m < n)
                {
                    for (; m < n; m++)
                    {
                        prefmap[m, 0] = 0; prefmap[m, 1] = 0;
                    }
                    m++;
                }
                else
                {
                    m++;
                }
            }

            //索引区
            phoneArr = new long[RecordSize];
            phonemap = new long[RecordSize, 2];
            for (int i = 0; i < RecordSize; i++)
            {
                long p = 16 + PrefSize * 9 + (i * 7);
                phoneArr[i] = BytesToLong(data[p], data[1 + p], data[2 + p], data[3 + p]);
                phonemap[i, 0] = data[4 + p] + ((data[5 + p]) << 8);
                phonemap[i, 1] = data[6 + p];
            }



        }
        private void Watch()
        {
            FileInfo fi = new FileInfo(datPath);
            FileSystemWatcher watcher = new FileSystemWatcher(fi.DirectoryName)
            {
                IncludeSubdirectories = false,
                NotifyFilter = NotifyFilters.LastWrite,
                Filter = "qqzeng-phone.dat",
            };

            watcher.Changed += (s, e) =>
            {

                var lastWriteTime = File.GetLastWriteTime(datPath);

                if (lastWriteTime > lastRead)
                {
                    //延时 解决 正由另一进程使用,因此该进程无法访问此文件
                    Thread.Sleep(1000);

                    LoadDat();
                    lastRead = lastWriteTime;
                }
            };
            watcher.EnableRaisingEvents = true;
        }




        /// <summary>
        /// 号段查询
        /// </summary>
        /// <param name="phone">7位或者11位</param>
        /// <returns></returns>
        public string Query(string phone)
        {
            long pref;
            long val = PhoneToInt(phone, out pref);
            long low = prefmap[pref, 0], high = prefmap[pref, 1];
            if (high == 0)
            {
                return "";
            }
            long cur = low == high ? low : BinarySearch(low, high, val);
            if (cur != -1)
            {

                return addrArr[phonemap[cur, 0]] + "|" + ispArr[phonemap[cur, 1]];
            }
            else
            {
                return "";
            }






        }
        /// <summary>
        /// 二分算法
        /// </summary>
        private int BinarySearch(long low, long high, long key)
        {
            if (low > high)
                return -1;
            else
            {
                long mid = (low + high) / 2;
                long phoneNum = phoneArr[mid];
                if (phoneNum == key)
                    return (int)mid;
                else if (phoneNum > key)
                    return BinarySearch(low, mid - 1, key);
                else
                    return BinarySearch(mid + 1, high, key);
            }
        }



        private long PhoneToInt(string phone, out long prefix)
        {
            //最高性能
            char ch;
            long currentValue = 0;
            long prefval = 0;
            unsafe
            {
                fixed (char* name = phone)
                {
                    for (int current = 0; current < 7; current++)
                    {
                        ch = name[current];
                        int digitValue = ch - '0';
                        currentValue = (currentValue * 10) + digitValue;
                        if (current == 2)
                        {
                            prefval = currentValue;
                        }
                    }
                }
                prefix = prefval;
                return currentValue;
            }


            //prefix = Convert.ToUInt32(phone.Substring(0,3));
            //return Convert.ToUInt32(phone.Substring(0, 7)); ;
        }



        /// <summary>
        /// 字节转整形 小节序 
        /// </summary>     
        private uint BytesToLong(byte a, byte b, byte c, byte d)
        {
            return (uint)(a | (b << 8) | (c << 16) | (d << 24));
        }



    }

    /*
    (调用例子):    
    string result = PhoneSearchFast.Instance.Query("号段|号码");
   --> result="省份|城市|区号|邮编|行政区划代码|运营商"
    */
}

最新手机号段归属地数据库 高性能dat解析[通俗易懂]

 

更新历史: 

2020-08-15 458461条记录
2020-08-01 458084条记录
2020-07-15 458020条记录
2020-07-01 457441条记录
2020-06-01 454802条记录
2020-05-01 450433条记录
2020-04-01 450175条记录
2020-03-01 447897条记录
2020-01-01 442612条记录
2019-12-01 441831条记录
2019-11-01 439265条记录
2019-09-01 438615条记录
2019-08-01 437142条记录
2019-07-01 436804条记录
2019-06-01 430826条记录
2019-05-01 429052条记录
2019-04-01 424014条记录
2019-03-01 423850条记录
2019-02-01 423766条记录
2019-01-01 421973条记录
2018-12-01 415967条记录
2018-11-01 415806条记录
2018-10-01 415311条记录
2018-09-01 413015条记录
2018-08-01 411856条记录
2018-07-01 410765条记录
2018-06-01 405385条记录
2018-05-01 387892条记录
2018-03-01 382140条记录
2018-02-01 381409条记录
2018-01-01 381061条记录
2017-12-01 380357条记录
2017-11-01 369022条记录
2017-10-01 368360条记录
2017-08-01 366454条记录
2017-07-01 363952条记录
2017-06-01 362386条记录
2017-05-01 359938条记录
2017-04-01 359429条记录
2017-03-01 358215条记录
2017-02-01 358006条记录
2017-01-01 357213条记录
2016-12-01 354586条记录
2016-11-01 352898条记录
2016-10-15 352182条记录
2016-09-15 352176条记录
2016-08-15 352069条记录
2016-07-15 344348条记录
2016-06-15 343198条记录
2016-05-15 335588条记录
2016-04-15 335169条记录
2016-03-25 334447条记录
2016-03-01 331878条记录
2016-02-01 329833条记录
2016-01-01 327154条记录
2015-12-01 326601条记录
2015-11-01 326596条记录
2015-10-01 324557条记录
2015-09-01 321602条记录
2015-08-01 320432条记录
2015-07-01 320027条记录
2015-06-01 318201条记录
2015-05-01 318115条记录
2015-04-01 317191条记录
2015-03-01 312145条记录
2015-02-01 311924条记录
2015-01-01 310165条记录
2014-12-01 309966条记录
2014-11-01 309398条记录
2014-10-01 307924条记录
2014-09-01 306093条记录
2014-08-01 301472条记录
2014-07-01 303033条记录
2014-06-01 300635条记录
2014-05-01 299920条记录
2014-04-01 296010条记录
2014-03-01 289087条记录
2014-02-01 288831条记录
2014-01-01 288661条记录
2013-12-01 287379条记录
2013-11-01 286438条记录
2013-10-01 286418条记录
2013-09-01 284304条记录
2013-08-01 282136条记录
2013-07-01 281965条记录
2013-06-03 281413条记录
2013-05-03 281071条记录
2013-04-01 279680条记录
2013-03-01 276893条记录
2013-02-01 275967条记录
2013-01-01 274995条记录
2012-12-01 274832条记录
…………

 

 

Excel vlookup  函数  xls 使用

 归属地公式:=(VLOOKUP(LEFT(B2,7),号段数据库!B:D,2,0)&VLOOKUP(LEFT(B2,7),号段数据库!B:D,3,0))

 运营商公式:=(VLOOKUP(LEFT(A2,3),isp!A:B,2,0))
 运营商公式:=(VLOOKUP(LEFT(B2,7),号段数据库!B:E,4,0))

 两个列合并:=CONCATENATE(B1&C1)

 

 最新手机号段归属地数据库 高性能dat解析[通俗易懂]

开发参考 GitHub  https://github.com/zengzhan/qqzeng-ip

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163138.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Scripting.FileSystemObject 的文件复制,删除,移动操作

    Scripting.FileSystemObject 的文件复制,删除,移动操作<%’创建一个FileSystemObject的事例SetMyFileObject=Server.CreateObject(“Scripting.FileSystemObject”)’创建一个要进行操作的文件SetMyFile=MyFileObject.CreateTextFile(“c:\test.txt”)MyFile.WriteLine(“Hello”)MyFile.Close’复…

    2022年7月14日
    69
  • jQuery特效 隔行变色

    jQuery特效 隔行变色

    2022年1月29日
    34
  • 可控制导航下拉方向的jQuery下拉菜单代码

    效果:http://hovertree.com/texiao/nav/1/代码如下:转自:http://hovertree.com/h/bjaf/kxl2s00m.htm特效:http://www

    2021年12月23日
    50
  • 如何安装dosbox(pycharm详细安装教程)

    创作日志:去年学了计组与汇编,用的是masm集成版,今年做汇编课设的时候,发现那个masm集成版不支持打开文件的操作,然后我就重拾DOSBox,发现自己不会用==,忘得干干净净,而且网上都是啥乱七八糟的呀,没有一个完整的教程,刚开始我都不知道还需要MASM.EXE和LINK.EXE的文件,有的又说要放到根目录下面啥子的,但是能不能讲清楚一点啊!于是就去问了俺的盆友,几句话解决…一、DOSBox先装好,执行文件下载好1、在某个盘里(据说千万别放C盘里,俺也不知道为啥),创建个

    2022年4月18日
    46
  • linux redis重启,互联网常识:linux下重启redis的方法

    linux redis重启,互联网常识:linux下重启redis的方法跟大家讲解下有关 linux 下重启 redis 的方法 相信小伙伴们对这个话题应该也很关注吧 现在就为小伙伴们说说 linux 下重启 redis 的方法 小编也收集到了有关 linux 下重启 redis 的方法的相关资料 希望大家看到了会喜欢 导语 已经将 redis 加入到 etc 下此时服务器启动 redis 也启动但是却连不上 redis 所有有了以下的过程 学习视频分享 redis 视频教程 查看 redis 状态 syst

    2025年6月1日
    4
  • HttpServlet 笔记

    HttpServlet 笔记HttpServlet 类包含 doGet doPost doPut doDelete doHead doOptions doTrace doGet 与 doPost 的区别 doGet 和 doPost 两个方法根据 HTTP 请求的不同会被分别调用 二者明显的区别是在使用 doGet 方法时请求 URL 会包含所要传递的参数 而在使用 doPost 方法时则不会 产生这种区

    2025年10月5日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号