最新手机号段归属地数据库(2021年4月发行版) 473101行
基于:最新手机号段归属地数据库
名称:手机号码归属地查询 dat高效率查询
压缩:原版txt为25M,生成这种dat结构为2.86M
性能:每秒解析300w+ ,简洁高效
创建:qqzeng-ip
开发参考 手机归属地查询 c# java php 解析dat 内存优化版
快速内存数据库Redis版 以及 导入数据库 mysql mssql 脚本
https://github.com/zengzhan/qqzeng-ip
微信小程序 号段归属地查询

最新手机号段归属地数据库
最新 手机号段数据库 号码归属地数据库 移动号段 联通号段 电信号段 虚拟运营商
权威 全面 准确 规范
字段包括 省份 城市 运营商 邮编 区号 等信息,对于数据分析、号码归属地查询等非常有帮助
更新历史:
2021-04-01 473101条记录 xlsx+txt+csv+mysql+mssql
2021-03-01 472529条记录
2021-02-01 472019条记录
2021-01-01 471402条记录
2020-12-01 465883条记录
2020-11-01 464737条记录
2020-10-01 463471条记录
2020-09-01 459519条记录
2020-08-15 458461条记录
2020-08-01 458084条记录
2020-07-15 458020条记录
2020-07-01 457441条记录
2020-06-15 455731条记录
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-10-01 439025条记录
2019-09-01 438615条记录
2019-08-01 437124条记录
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 398209条记录
2018-04-01 387892条记录
2018-03-01 382140条记录
2017-07-01 363952条记录
2017-06-01 362386条记录
2017-05-01 359938条记录
…………
2013-04-01 279680条记录
2013-03-01 276893条记录
2013-02-01 275967条记录
2013-01-01 274995条记录
2012-12-01 274832条记录
…………

移动号段:
134 135 136 137 138 139 147 148 150 151 152 157 158 159 172 178 182 183 184 187 188 195 198
联通号段:
130 131 132 145 146 155 156 166 167 171 175 176 185 186 196
电信号段:
133 149 153 173 174 177 180 181 189 191 193 199
虚拟运营商:
162 165 167 170 171
字段样例

//名称:手机号码归属地查询 dat高效率查询 内存优化版
//压缩:原版txt为22M,生成这种dat结构为2.66M
//性能:每秒解析300万+号段或者号码,简洁高效
//环境:CPU i7-7700K +内存16GB
//创建:qqzeng-ip 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-199private 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);elsereturn 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="省份|城市|区号|邮编|行政区划代码|运营商"*/
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace qqzeng_phone_dat
{public class PhoneSearch{private Dictionary<uint, PrefixIndex> prefixDict;private byte[] indexBuffer;private byte[] data;long firstPhoneOffset;//索引区第一条流位置long lastPhoneOffset;//索引区最后一条流位置long prefixStartOffset;//前缀区第一条的流位置long prefixEndOffset;//前缀区最后一条的流位置long phoneCount; //号段段数量long prefixCount; //前缀数量/// <summary>/// 初始化二进制dat数据/// </summary>/// <param name="dataPath"></param>public PhoneSearch(string dataPath){using (FileStream fs = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read)){data = new byte[fs.Length];fs.Read(data, 0, data.Length);}firstPhoneOffset = BytesToLong(data[0], data[1], data[2], data[3]);lastPhoneOffset = BytesToLong(data[4], data[5], data[6], data[7]);prefixStartOffset = BytesToLong(data[8], data[9], data[10], data[11]);prefixEndOffset = BytesToLong(data[12], data[13], data[14], data[15]);phoneCount = (lastPhoneOffset - firstPhoneOffset) / 8 + 1; //索引区块每组 8字节 prefixCount = (prefixEndOffset - prefixStartOffset) / 9 + 1; //前缀区块每组 9字节//初始化前缀对应索引区区间indexBuffer = new byte[prefixCount * 9];Array.Copy(data, prefixStartOffset, indexBuffer, 0, prefixCount * 9);prefixDict = new Dictionary<uint, PrefixIndex>();for (var k = 0; k < prefixCount; k++){int i = k * 9;uint prefix = (uint)indexBuffer[i];long start_index = BytesToLong(indexBuffer[i + 1], indexBuffer[i + 2], indexBuffer[i + 3], indexBuffer[i + 4]);long end_index = BytesToLong(indexBuffer[i + 5], indexBuffer[i + 6], indexBuffer[i + 7], indexBuffer[i + 8]);prefixDict.Add(prefix, new PrefixIndex() { prefix = prefix, start_index = start_index, end_index = end_index });}}public static uint PhoneToInt(string phone, out uint prefix){prefix = Convert.ToUInt32(phone.Substring(0, 3));return Convert.ToUInt32(phone.Substring(0, 7)); ;}/// <summary>/// 号段查询/// </summary>/// <param name="phone">7位或者11位</param>/// <returns></returns>public string Query(string phone){uint phone_prefix_value;uint intPhone = PhoneToInt(phone, out phone_prefix_value);uint high = 0;uint low = 0;uint local_offset = 0;uint local_length = 0;if (prefixDict.ContainsKey(phone_prefix_value)){low = (uint)prefixDict[phone_prefix_value].start_index;high = (uint)prefixDict[phone_prefix_value].end_index;}else{return "";}uint my_index = low == high ? low : BinarySearch(low, high, intPhone);GetIndex(my_index, out local_offset, out local_length);return GetLocal(local_offset, local_length);}/// <summary>/// 二分算法/// </summary>public uint BinarySearch(uint low, uint high, uint k){uint M = 0;while (low <= high){uint mid = (low + high) / 2;uint phoneNum = GetIntPhone(mid);if (phoneNum >= k){M = mid;if (mid == 0){break; //防止溢出}high = mid - 1;}elselow = mid + 1;}return M;}/// <summary>/// 在索引区解析/// </summary>/// <param name="left">ip第left个索引</param>/// <param name="startip">返回开始ip的数值</param>/// <param name="endip">返回结束ip的数值</param>/// <param name="local_offset">返回地址信息的流位置</param>/// <param name="local_length">返回地址信息的流长度</param>private void GetIndex(uint left, out uint local_offset, out uint local_length){long left_offset = firstPhoneOffset + (left * 8);local_offset = (uint)data[4 + left_offset] + (((uint)data[5 + left_offset]) << 8) + (((uint)data[6 + left_offset]) << 16);local_length = (uint)data[7 + left_offset];}/// <summary>/// 返回归属地信息/// </summary>/// <param name="local_offset">地址信息的流位置</param>/// <param name="local_length">地址信息的流长度</param>/// <returns></returns>private string GetLocal(uint local_offset, uint local_length){byte[] buf = new byte[local_length];Array.Copy(data, local_offset, buf, 0, local_length);return Encoding.UTF8.GetString(buf, 0, (int)local_length);// return Encoding.GetEncoding("GB2312").GetString(buf, 0, (int)local_length);}private uint GetIntPhone(uint left){long left_offset = firstPhoneOffset + (left * 8);return BytesToLong(data[0 + left_offset], data[1 + left_offset], data[2 + left_offset], data[3 + left_offset]);}/// <summary>/// 字节转整形 小节序 /// </summary> private uint BytesToLong(byte a, byte b, byte c, byte d){return ((uint)a << 0) | ((uint)b << 8) | ((uint)c << 16) | ((uint)d << 24);}}/*(调用例子):PhoneSearch finder = new PhoneSearch("qqzeng-phone.dat");string result = finder.Query("号段或者号码");--> result="省份|城市|运营商|区号|邮编|行政区划代码"*/
}
开发:https://github.com/zengzhan/qqzeng-ip