根据IP地址自动识别省份城市



功能说明:需要获取客户端的IP地址,自动识别省份


代码如下:

获取IP地址:

 public static String getIpAddr(HttpServletRequest request) { 
String ip = request.getHeader("X-Forwarded-For"); 
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 
ip = request.getHeader("Proxy-Client-IP"); 

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 
ip = request.getHeader("WL-Proxy-Client-IP"); 

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 
ip = request.getHeader("HTTP_CLIENT_IP"); 

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 
ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) 
ip = request.getRemoteAddr(); 

if ("0:0:0:0:0:0:0:1".equals(ip.trim())) { 
ip = "127.0.0.1"; 
} 
return ip; 
}
调用
String clientIp = PortalToolsUtil.getIpAddr(portalRequest);

根据IP地址获取省份类:

public class IpAddress {
    
    private Logger LogUtil = Logger.getLogger(IpAddress.class);
    // 随机文件访问类
    private RandomAccessFile ipFile = null;
    // 单一模式实例
    private static IpAddress instance = new IpAddress();
    // ip开始结束位置
    private long ipBegin = 0L;
    private long ipEnd = 0L;
    // ip总数
    private long ipSum = 0L;
    // 国家,地区
    private String country = "";
    private String area = "";

    // 一些固定常量,比如记录长度等等
    private static final int RECORD_LENGTH = 7;
    private static final byte AREA_FOLLOWED = 0x01;
    private static final byte NO_AREA = 0x02;

    /*
     * 私有构造函数
     */
    private IpAddress() {
        // 数据库地址
        String dataPath = PropUtil.getProp("ipfile");
        try {
            ipFile = new RandomAccessFile(new File(dataPath).getAbsolutePath(),"r");
        } catch (FileNotFoundException e) {
            LogUtil.error("IP地址信息文件没有找到(QQWry.Dat),IP显示功能将无法使用");
        }
        if (ipFile != null) {
            try {
                ipBegin = byteArrayToLong(readBytes(0, 4));
                ipEnd = byteArrayToLong(readBytes(4, 4));
                if (ipBegin == -1 || ipEnd == -1) {
                    ipFile.close();
                    ipFile = null;
                }
            } catch (IOException e) {
                LogUtil.error("IP地址信息文件格式有错误,IP显示功能将无法使用");
            }
        }
        ipSum = (ipEnd - ipBegin) / RECORD_LENGTH + 1;
    }

    /**
     * 在指定位置读取一定数目的字节
     *
     * @param offset
     *            位置
     * @param num
     *            多少个字节
     * @return ret
     */
    private byte[] readBytes(long offset, int num) {
        byte[] ret = new byte[num];
        try {
            ipFile.seek(offset);

            for (int i = 0; i != num; i++) {
                ret[i] = ipFile.readByte();
            }
            return ret;
        } catch (IOException e) {
            LogUtil.error("读取文件失败_readBytes");
            return ret;
        }
    }

    /**
     * 当前位置读取一定数目的字节
     *
     * @param num
     *            多少个字节
     * @return ret
     */
    private byte[] readBytes(int num) {
        byte[] ret = new byte[num];
        try {
            for (int i = 0; i != num; i++) {
                ret[i] = ipFile.readByte();
            }
            return ret;
        } catch (IOException e) {
            LogUtil.error("读取文件失败_readBytes");
            return ret;
        }
    }

    /**
     * 对little-endian字节序进行了转换 byte[]转换为long
     *
     * @param b
     * @return ret
     */
    private long byteArrayToLong(byte[] b) {
        long ret = 0;
        for (int i = 0; i < b.length; i++) {
            ret |= (b[i] << (0x8 * i) & (0xFF * (long) (Math.pow(0x100, i))));
        }
        return ret;
    }

    /**
     * 对little-endian字节序进行了转换
     *
     * @param ip
     *            ip的字节数组形式
     * @return ip的字符串形式
     */
    private String byteArrayToStringIp(byte[] ip) {
        StringBuffer sb = new StringBuffer();
        for (int i = ip.length - 1; i >= 0; i--) {
            sb.append(ip[i] & 0xFF);
            sb.append(".");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    /**
     * 把ip字符串转换为long型
     *
     * @param ip
     * @return long
     */
    private long StingIpToLong(String ip) {
        String[] arr = ip.split("\\.");
        return (Long.valueOf(arr[0]).longValue() * 0x1000000
                + Long.valueOf(arr[1]).longValue() * 0x10000
                + Long.valueOf(arr[2]).longValue() * 0x100 + Long.valueOf(
                arr[3]).longValue());
    }

    /**
     * 搜索ip,二分法
     *
     * @param ip
     * @return long ip所在位置
     */
    public long seekIp(String ip) {
        long tmp = StingIpToLong(ip);
        long i = 0;
        long j = ipSum;
        long m = 0;
        long lm = 0L;
        while (i < j) {
            m = (i + j) / 2;
            lm = m * RECORD_LENGTH + ipBegin;
            if (tmp == byteArrayToLong(readBytes(lm, 4))) {
                return byteArrayToLong(readBytes(3));
            } else if (j == (i + 1)) {
                return byteArrayToLong(readBytes(3));
            } else if (tmp > byteArrayToLong(readBytes(lm, 4))) {
                i = m;
            } else/* if( tmp < byteArrayToLong(readBytes(lm, 4))) */{
                j = m;
            }
        }
        //LogUtil.error("没有找到ip");
        return -1L;
    }

    private String readArea(long offset) throws IOException {
        ipFile.seek(offset);
        byte b = ipFile.readByte();
        if (b == 0x01 || b == 0x02) {
            long areaOffset = byteArrayToLong(readBytes(offset + 1, 3));
            // if(areaOffset == 0)
            // return "未知";
            // else
            return readString(areaOffset);
        } else
            return readString(offset);
    }

    /**
     * 通过ip位置获取国家地区, 参照纯真ip数据库结构
     *
     * @param offset
     * @return 国家+地区
     */
    private String seekCountryArea(long offset) {
        try {
            ipFile.seek(offset + 4);
            byte b = ipFile.readByte();
            if (b == AREA_FOLLOWED) {
                long countryOffset = byteArrayToLong(readBytes(3));
                ipFile.seek(countryOffset);
                b = ipFile.readByte();
                if (b == NO_AREA) {
                    country = readString(byteArrayToLong(readBytes(3)));
                    ipFile.seek(countryOffset + 4);
                } else
                    country = readString(countryOffset);
                // area = readArea(ipFile.getFilePointer());
            } else if (b == NO_AREA) {
                country = readString(byteArrayToLong(readBytes(3)));
                // area = readArea(offset + 8);
            } else {
                country = readString(ipFile.getFilePointer() - 1);
                // area = readArea(ipFile.getFilePointer());
            }
            // return country + " " + area;
            String country1;
            if (country.length() >= 2)
                // 只取前两个字
                country1 = country.substring(0, 2);
            else
                country1 = country;
            return country1;
            // return CountryMap.getBranchCodeByCountryName(country1);

        } catch (IOException e) {
            return null;
        }
    }

    /**
     * 从offset偏移处读取一个以0结束的字符串
     *
     * @param offset
     * @return ret 读取的字符串,出错返回空字符串
     */
    private String readString(long offset) {
        try {
            ipFile.seek(offset);
            byte[] b = new byte[128];
            int i;
            for (i = 0; (b.length != i) && ((b[i] = ipFile.readByte()) != 0); i++)
                ;
            String ret = new String(b, 0, i, "GBK");
            ret = ret.trim();
            return (ret.equals("") || ret.indexOf("CZ88.NET") != -1) ? "未知"
                    : ret;
        } catch (IOException e) {
            LogUtil.error("读取文件失败_readString");
        }
        return "";
    }

    /**
     * 包含字符串的ip记录
     *
     * @param addr
     *            地址
     * @return IpRecord ip记录
     */

    public ArrayList stringToIp(String addr) {
        ArrayList ret = new ArrayList();
        try {
            FileChannel fc = ipFile.getChannel();
            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0,
                    ipFile.length());
            mbb.order(ByteOrder.LITTLE_ENDIAN);
            // 上面3代码未使用,内存映射文件功能未写

            for (long i = ipBegin + 4; i != ipEnd + 4; i += RECORD_LENGTH) {
                String sca = seekCountryArea(byteArrayToLong(readBytes(i, 3)));
                if (sca.indexOf(addr) != -1) {
                    IpRecord rec = new IpRecord();
                    rec.address = sca;
                    rec.beginIp = byteArrayToStringIp(readBytes(i - 4, 4));
                    rec.endIp = byteArrayToStringIp(readBytes(i + 3, 4));
                    ret.add(rec);
                }
            }
        } catch (IOException e) {
            LogUtil.error(e.getMessage());
        }
        return ret;
    }

    /**
     * 封装ip记录,包括开始ip,结束ip和地址
     */
    private class IpRecord {
        public String beginIp;
        public String endIp;
        public String address;

        public IpRecord() {
            beginIp = endIp = address = "";
        }

        public String toString() {
            return beginIp + " - " + endIp + " " + address;
        }
    }

    /**
     * @return 单一实例
     */
    public static IpAddress getInstance() {
        return instance;
    }

    /**
     * @param ip
     * @return ret
     */
    public String IpStringToAddress(String ip) {
        // 这里要添加ip格式判断
        // public boolean isIP(Strin ip)
        long ipOffset = seekIp(ip);
        String ret = seekCountryArea(ipOffset);
        return ret;
    }

    /**
     * @return IpSum
     */
    public long getIpSum() {
        return ipSum;
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        IpAddress ipAddr = IpAddress.getInstance();
        // //ip总数
        // long l = ipAddr.getIpSum();
        // LogUtil.error(l);
        // 测试
        String str = ipAddr.IpStringToAddress("218.65.88.101");
        System.out.println(str);
        //LogUtil.error(str);

        /*
         * java.net.InetAddress addr = null; try{ addr =
         * java.net.InetAddress.getLocalHost();
         * }catch(java.net.UnknownHostException e){ e.printStackTrace(); }
         * String ip=addr.getHostAddress().toString();//获得本机IP
         * System.out.print(ip); String
         * address=addr.getHostName().toString();//获得本机名称
         * System.out.print(address); str = ipAddr.IpStringToAddress(ip);
         * LogUtil.error(str);
         */

        // ArrayList al = ipAddr.stringToIp("网吧");
        // Iterator it = al.iterator();
        //
        // File f = new File("ipdata.txt");
        // try {
        // if (!f.exists()) {
        // f.createNewFile();
        // }
        // BufferedWriter out = new BufferedWriter(
        // new OutputStreamWriter(
        // new FileOutputStream(f, true)
        // )
        // );
        // int i = 0;
        // while (it.hasNext()) {
        // out.write(it.next().toString());
        // out.newLine();
        // i++;
        // }
        // out.write(new Date().toString());
        // out.write("总共搜索到 " + i);
        // out.close();
        // } catch (IOException e) {
        // e.printStackTrace();
        // }
    }
}

注意事项:QQWry.Dat可以百度从网上下载,但该文件为GBK编码,读取时需要加编码,如代码中红色标注

你可能感兴趣的:(根据IP地址自动识别省份城市)