根据IP地址获取真实IP所在地区 ,使用纯真IP库(纯真版20160215)



package com.alpha.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;

/**
 * @说明: 根据IP地址获取真实IP所在地区 ,使用纯真IP库(纯真版20160215)
 * @作者: JavaAlpha
 * @日期: 2016年2月24日上午11:43:46
 * @版本: V1.0
 */
public class IPParser {

    private static final String DATA_PATH = "qqwry.dat";

    // 获取指定IP的城市
    public static String getCountry(String ip) {
        return new SubIPParser(DATA_PATH).seek(ip).getCountry();
    }

    // 获取指定IP的位置
    public static String getLocal(String ip) {
        return new SubIPParser(DATA_PATH).seek(ip).getLocation();
    }

    // 获取指定IP的城市+位置
    public static String getForSeparator(String ip, String sep) {
        SubIPParser parser = new SubIPParser(DATA_PATH).seek(ip);
        return parser.getCountry() + sep + parser.getLocation();
    }

    private IPParser() {
    }

    // 对原版代码做了重构,逻辑保持不变;
    static class SubIPParser {
        private String dataClasspath;

        private String country;

        private String location;

        private int recordCount, countryFlag;

        private long rangE, rangB, offSet, startIP, endIP, firstStartIP, lastStartIP, endIPOff;

        public SubIPParser(String classpath) {
            dataClasspath = classpath;
        }

        public SubIPParser seek(String ip) {
            RandomAccessFile fis = null;
            byte[] buff = null;
            long ipn;
            try {
                ipn = ipToLong(ip);
                fis = new RandomAccessFile(getDataPath().getFile(), "r");
                buff = new byte[4];
                fis.seek(0);
                fis.read(buff);
                firstStartIP = this.byteToLong(buff);
                fis.read(buff);
                lastStartIP = this.byteToLong(buff);
                recordCount = (int) ((lastStartIP - firstStartIP) / 7);
                if (recordCount <= 1) {
                    location = country = "未知";
                    return this;
                }
                rangB = 0;
                rangE = recordCount;
                long RecNo;
                do {
                    RecNo = (rangB + rangE) / 2;
                    loadStartIP(RecNo, fis);
                    if (ipn == startIP) {
                        rangB = RecNo;
                        break;
                    }
                    if (ipn > startIP)
                        rangB = RecNo;
                    else
                        rangE = RecNo;
                } while (rangB < rangE - 1);
                loadStartIP(rangB, fis);
                loadEndIP(fis);
                loadCountry(ipn, fis);
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                    }
                }
            }
            return this;
        }

        public String getLocation() {
            return this.location;
        }

        public String getCountry() {
            return this.country;
        }

        private long byteToLong(byte[] b) {
            long ret = 0;
            for (int i = 0; i < b.length; i++) {
                long t = 1L;
                for (int j = 0; j < i; j++) {
                    t = t * 256L;
                }
                ret += ((b[i] < 0) ? 256 + b[i] : b[i]) * t;
            }
            return ret;
        }

        private long ipToLong(String ip) {
            String[] arr = ip.split("\\.");
            long ret = 0;
            for (int i = 0; i < arr.length; i++) {
                long l = 1;
                for (int j = 0; j < i; j++)
                    l *= 256;
                try {
                    ret += Long.parseLong(arr[arr.length - i - 1]) * l;
                } catch (Exception e) {
                    ret += 0;
                }
            }
            return ret;
        }

        private URL getDataPath() {
            URL url = null;
            url = Thread.currentThread().getContextClassLoader().getResource(dataClasspath);
            if (url == null) {
                url = IPParser.class.getClassLoader().getResource(dataClasspath);
            }
            return url;
        }

        private String getFlagStr(long OffSet, RandomAccessFile fis) throws IOException {
            int flag = 0;
            byte[] buff = null;
            do {
                fis.seek(OffSet);
                buff = new byte[1];
                fis.read(buff);
                flag = (buff[0] < 0) ? 256 + buff[0] : buff[0];
                if (flag == 1 || flag == 2) {
                    buff = new byte[3];
                    fis.read(buff);
                    if (flag == 2) {
                        countryFlag = 2;
                        endIPOff = OffSet - 4;
                    }
                    OffSet = this.byteToLong(buff);
                } else
                    break;
            } while (true);

            if (OffSet < 12) {
                return "";
            } else {
                fis.seek(OffSet);
                return getText(fis);
            }
        }

        private String getText(RandomAccessFile fis) throws IOException {
            long len = fis.length();
            ByteArrayOutputStream byteout = new ByteArrayOutputStream();
            byte ch = fis.readByte();
            do {
                byteout.write(ch);
                ch = fis.readByte();
            } while (ch != 0 && fis.getFilePointer() < len);
            return byteout.toString("gbk");
        }

        private void loadCountry(long ipn, RandomAccessFile fis) throws IOException {
            if (countryFlag == 1 || countryFlag == 2) {
                country = getFlagStr(endIPOff + 4, fis);
                if (countryFlag == 1) {
                    location = getFlagStr(fis.getFilePointer(), fis);
                    if (ipn >= ipToLong("255.255.255.0") && ipn <= ipToLong("255.255.255.255")) {
                        location = getFlagStr(endIPOff + 21, fis);
                        country = getFlagStr(endIPOff + 12, fis);
                    }
                } else {
                    location = getFlagStr(endIPOff + 8, fis);
                }
            } else {
                country = getFlagStr(endIPOff + 4, fis);
                location = getFlagStr(fis.getFilePointer(), fis);
            }
        }

        private long loadEndIP(RandomAccessFile fis) throws IOException {
            byte[] buff = null;
            fis.seek(endIPOff);
            buff = new byte[4];
            fis.read(buff);
            endIP = this.byteToLong(buff);
            buff = new byte[1];
            fis.read(buff);
            countryFlag = (buff[0] < 0) ? 256 + buff[0] : buff[0];
            return endIP;
        }

        private long loadStartIP(long RecNo, RandomAccessFile fis) throws IOException {
            byte[] buff = null;
            offSet = firstStartIP + RecNo * 7;
            fis.seek(offSet);
            buff = new byte[4];
            fis.read(buff);
            startIP = this.byteToLong(buff);
            buff = new byte[3];
            fis.read(buff);
            endIPOff = this.byteToLong(buff);
            return startIP;
        }
    }

    public static void main(String[] args) throws Exception {
        long initUsedMemory = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
        long start = System.currentTimeMillis();
        // 查询IP地址
        System.out.println(IPParser.getForSeparator("59.132.170.186", ", "));
        long end = System.currentTimeMillis();
        long endUsedMemory = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
        // 性能测试
        System.out.println("time spent:" + (end - start) + " ms");
        System.out.println("memory consumes:" + (endUsedMemory - initUsedMemory) / 1024 + " kb");
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
北京市---市辖区---东城区---东华门街道办事处 北京市---市辖区---东城区---景山街道办事处 北京市---市辖区---东城区---交道口街道办事处 北京市---市辖区---东城区---安定门街道办事处 北京市---市辖区---东城区---北新桥街道办事处 北京市---市辖区---东城区---东四街道办事处 北京市---市辖区---东城区---朝阳门街道办事处 北京市---市辖区---东城区---建国门街道办事处 北京市---市辖区---东城区---东直门街道办事处 北京市---市辖区---东城区---和平里街道办事处 北京市---市辖区---东城区---前门街道办事处 北京市---市辖区---东城区---崇文门外街道办事处 北京市---市辖区---东城区---东花市街道办事处 北京市---市辖区---东城区---龙潭街道办事处 北京市---市辖区---东城区---体育馆路街道办事处 北京市---市辖区---东城区---天坛街道办事处 北京市---市辖区---东城区---永定门外街道办事处 北京市---市辖区---西城区---西长安街街道办事处 北京市---市辖区---西城区---新街口街道办事处 北京市---市辖区---西城区---月坛街道办事处 北京市---市辖区---西城区---展览路街道办事处 北京市---市辖区---西城区---德胜街道办事处 北京市---市辖区---西城区---金融街街道办事处 北京市---市辖区---西城区---什刹海街道办事处 北京市---市辖区---西城区---大栅栏街道办事处 北京市---市辖区---西城区---天桥街道办事处 北京市---市辖区---西城区---椿树街道办事处 北京市---市辖区---西城区---陶然亭街道办事处 北京市---市辖区---西城区---广安门内街道办事处 北京市---市辖区---西城区---牛街街道办事处 北京市---市辖区---西城区---白纸坊街道办事处 北京市---市辖区---西城区---广安门外街道办事处 北京市---市辖区---朝阳区---建外街道办事处 北京市---市辖区---朝阳区---朝外街道办事处 北京市---市辖区---朝阳区---呼家楼街道办事处 北京市---市辖区---朝阳区---三里屯街道办事处 北京市---市辖区---朝阳区---左家庄街道办事处 北京市---市辖区---朝阳区---香河园街道办事处 北京市---市辖区---朝阳区---和平街街道办事处 北京市---市辖区---朝阳区---安贞街道办事处 北京市---市辖区---朝阳区---亚运村街道办事处 北京市---市辖区---朝阳区---小关街道办事处 北京市---市辖区---朝阳区---酒仙桥街道办事处 北京市---市辖区---朝阳区---麦子店街道办事处 北京市---市辖区---朝阳区---团结湖街道办事处 北京市---市辖区---朝阳区---六里屯街道办事处 北京市---市辖区---朝阳区---八里庄街道办事处 北京市---市辖区---朝阳区---双井街道办事处 北京市---市辖区---朝阳区---劲松街道办事处 北京市---市辖区---朝阳区---潘家园街道办事处 北京市---市辖区---朝阳区---垡头街道办事处 北京市---市辖区---朝阳区---南磨房地区办事处 北京市---市辖区---朝阳区---高碑店地区办事处 北京市---市辖区---朝阳区---将台地区办事处

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值