概述
根据输入ip,使用二分法获得ip对应的省市信息。
处理掉无效数据后,数据量大小不到20MB,使用一个MAP,一个SET,占用内存不多,可以作为一个接口服务使用。
输入ip地址,输出ip地址对应的省市。
内容格式如下:
IP开始 | IP结束 | 国家 | 省 | 市 | 区县 | 区域Code |
代码如下:
/**
*
*
* 根据输入ip,使用二分法算法获得省市信息
*
* 第一位ip255 *256*256*256 = 4278190080,
* 目前数据中最大值为224 *256*256*256=3758096384,也超过int正数最大值2147483647,所以要使用long类型存储ip地址转后的值
* result=first+second+third+forth是将ip地址转为long类型。每一位ip通过移动位置的操作,保证每一位ip的值不会覆盖。
*
*/
object IP2CityInfo {
//声明排序后的long类型ip集合
var sorted:Seq[Long]=_
//构建低位ip地址(就是第一位ip的值)与省市的映射
val ip2city=mutable.Map[Long,String]()
def main(args: Array[String]) {
val input=Source.fromFile("/Users/path/final_ip.txt")
val lines= input.getLines()
//用于测试,存储省市信息为未知的记录,用于后续将数据源进行再次处理
val ip2cityError=mutable.Set[String]()
//用于测试,记录中第一个ip地址信息是否有重复
var total=0
val set=mutable.Set[Long]()
lines.foreach(line=>{
val fields = line.split("t")
val province=fields(3)
val city=fields(4)
var cityInfo=province+","+city
if(province.equals(city)){
//当为直辖市的情况
cityInfo=province
}
val ip = fields.apply(0)
val result=ip2Long(ip)
if(!(province.equals("未知")||city.equals("未知"))){
ip2city.put(result,cityInfo)
}else{
ip2cityError.add(line)
}
set.add(result)
total=total+1
})
//total与set.size相等,表示ip地址转化为long类型,没有冲突
if(total==set.size){
println("ip地址转化为long类型,没有冲突")
}else{
println("ip地址转化为long类型,有冲突。即存在第一个ip值完全相同的记录")
}
println("输入记录总数:",total)
println("有效记录条数:",ip2city.size)
println("无效记录条数:",total-ip2city.size)
println("有效记录取样:")
for(e<-ip2city.take(10)){
println(e)
}
println("无效记录取样:")
for(e<-ip2cityError.take(10)){
println(e)
}
println("排序后记录取样:")
sorted=ip2city.keySet.toSeq.sorted
for(e<-sorted.take(10)){
println(e)
}
//test
println(ip2cityInfo("1.194.194.198"))
println(ip2cityInfo("1.194.4.198"))
}
/**
*
* 利用二分查找算法,根据输入的ip字符串省市信息,查询出包含此ip区间的
*
* @param ip 输入ip
* @return 省市信息
* */
def ip2cityInfo(ip :String):String= {
val value=ip2Long(ip)
var index=0
var min=0
var mid=0
var max=sorted.size-1
var break=true
while(min<=max && break){
//采用无符号右移一位,即可以表示除以2
mid = (min+max)>>>1
val midValue = sorted(mid)
if(midValue>value){
max = mid-1
}else if(sorted(mid)<value){
min = mid+1
}else{
index= mid
break=false
}
}
//当没有查询到结果,保证index取得最小的索引值
if(index==0){
index=Math.min(min,Math.min(mid,max))
}
ip2city(sorted(index))
}
/**
* 将ip字符串转化为long类型数字
*
* 使用第一个ip值的四位ip进行省市的锁定。如果使用前三段导致获得省市信息不准确
* 222.221.30.199 222.221.30.201 中国 云南省 昆明市 未知 530100
* 222.221.30.202 222.221.30.202 中国 云南省 保山市 昌宁县 530524
*
* */
def ip2Long(ip :String):Long={
val subIpArray = ip.split("\.")
val first=subIpArray(0).toLong * 256 * 256 * 256
val second=subIpArray(1).toLong * 256 * 256
val third=subIpArray(2).toLong * 256
val forth=subIpArray(3).toLong
val result=first+second+third+forth
result
}
}
最后
以上就是怕孤独奇迹为你收集整理的根据ip获得省市信息的全部内容,希望文章能够帮你解决根据ip获得省市信息所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复