zoukankan      html  css  js  c++  java
  • java通过IP地址获取物理位置

      1 import java.io.*;
      2 import java.util.*;
      3 import java.util.regex.Matcher;
      4 import java.util.regex.Pattern;
      5 import java.net.InetAddress;
      6 import java.net.UnknownHostException;
      7 import java.nio.ByteOrder;
      8 import java.nio.MappedByteBuffer;
      9 import java.nio.channels.FileChannel;
     10 
     11 /**
     12 * 纯真ip查询主程序
     13 * QQWry.Dat保存在当前目录
     14 * @author _hhh_
     15 * @version 0.1, 04/23/08
     16 */
     17 public class IpAddress {
     18 
     19    //数据库地址
     20    private String dataPath = "QQWry.dat";
     21    //随机文件访问类
     22    private RandomAccessFile ipFile = null;
     23    //单一模式实例
     24    private static IpAddress instance = new IpAddress();
     25    //ip开始结束位置
     26    private long ipBegin=0L;
     27    private long ipEnd=0L;
     28    //ip总数
     29    private long ipSum=0L;
     30    //国家,地区
     31    private String country="";
     32    private String area="";
     33 
     34    // 一些固定常量,比如记录长度等等
     35    private static final int RECORD_LENGTH = 7;
     36    private static final byte AREA_FOLLOWED = 0x01;
     37    private static final byte NO_AREA = 0x02;
     38 
     39    /*
     40    * 私有构造函数
     41    */
     42    private IpAddress() {
     43        try {
     44            ipFile = new RandomAccessFile(new File(dataPath).getAbsolutePath(), "r");
     45            } catch (FileNotFoundException e) {  
     46            System.out.println("IP地址信息文件没有找到,IP显示功能将无法使用");
     47            e.printStackTrace();
     48        }
     49        if(ipFile != null) {
     50            try {               
     51                ipBegin = byteArrayToLong(readBytes(0,4));
     52                ipEnd = byteArrayToLong(readBytes(4,4));
     53                if(ipBegin == -1 || ipEnd == -1) {
     54                    ipFile.close();
     55                    ipFile = null;
     56                }
     57            } catch (IOException e) {
     58                System.out.println("IP地址信息文件格式有错误,IP显示功能将无法使用");
     59                e.printStackTrace();
     60            }
     61        }
     62        ipSum = (ipEnd-ipBegin)/RECORD_LENGTH+1;
     63    }
     64 
     65    /**
     66    * 在指定位置读取一定数目的字节
     67    * @param offset 位置
     68    * @param num 多少个字节
     69    * @return ret 
     70    */
     71    private byte[] readBytes(long offset, int num) {
     72        byte[] ret = new byte[num];
     73        try {
     74            ipFile.seek(offset);
     75 
     76            for(int i=0; i != num; i++) {
     77                ret[i] = ipFile.readByte();
     78            }
     79            return ret;
     80        } catch (IOException e) {
     81            e.printStackTrace();
     82            System.out.println("读取文件失败_readBytes");
     83            return ret;
     84        }
     85    }
     86 
     87    /**
     88    * 当前位置读取一定数目的字节
     89    * @param num 多少个字节
     90    * @return ret 
     91    */
     92    private byte[] readBytes(int num) {
     93        byte[] ret = new byte[num];
     94        try {
     95            for(int i=0; i != num; i++) {
     96                ret[i] = ipFile.readByte();
     97            }
     98            return ret;
     99        } catch (IOException e) {
    100            System.out.println("读取文件失败_readBytes");
    101            return ret;
    102        }
    103    }
    104 
    105    /**
    106    * 对little-endian字节序进行了转换
    107    * byte[]转换为long
    108    * @param b
    109    * @return ret
    110    */
    111    private long byteArrayToLong(byte[] b) {
    112        long ret = 0;
    113        for(int i=0; i<b.length; i++) {
    114            ret |= ( b[i] << (0x8*i) & (0xFF * (long)(Math.pow(0x100,i))) );
    115        }
    116        return ret;
    117    }
    118 
    119    /**
    120    * 对little-endian字节序进行了转换
    121    * @param ip ip的字节数组形式
    122    * @return ip的字符串形式
    123    */
    124    private String byteArrayToStringIp(byte[] ip) {
    125        StringBuffer sb = new StringBuffer();
    126        for(int i=ip.length-1; i>=0; i--) {
    127            sb.append(ip[i] & 0xFF);
    128            sb.append(".");
    129        }
    130        sb.deleteCharAt(sb.length()-1);
    131        return sb.toString();
    132    }
    133 
    134    /**
    135    * 把ip字符串转换为long型
    136    * @param ip
    137    * @return long
    138    */
    139    private long StingIpToLong(String ip) {
    140        String[] arr = ip.split("\.");
    141        return (Long.valueOf(arr[0])*0x1000000 +
    142                Long.valueOf(arr[1])*0x10000 +
    143                Long.valueOf(arr[2])*0x100 +
    144                Long.valueOf(arr[3]));   
    145    }
    146 
    147    /**
    148    * 搜索ip,二分法
    149    * @param String ip字符串0.0.0.0到255.255.255.255
    150    * @return long ip所在位置
    151    */
    152    public long seekIp(String ip) {
    153        long tmp = StingIpToLong(ip);
    154        long i=0;
    155        long j=ipSum;
    156        long m = 0;
    157        long lm=0L;
    158        while(i<j) {
    159            m = (i+j)/2;
    160            lm = m*RECORD_LENGTH + ipBegin;
    161            if( tmp == byteArrayToLong(readBytes(lm, 4))){       
    162                return byteArrayToLong(readBytes(3));
    163            }else if(j==(i+1)) {
    164                return byteArrayToLong(readBytes(3));
    165            }else if( tmp > byteArrayToLong(readBytes(lm, 4))){
    166                i = m;
    167            }else/* if( tmp < byteArrayToLong(readBytes(lm, 4)))*/{
    168                j = m;
    169            }
    170        }
    171        System.out.println("没有找到ip");
    172        return -1L;
    173    }
    174    private String readArea(long offset) throws IOException {
    175        ipFile.seek(offset);
    176        byte b = ipFile.readByte();
    177        if(b == 0x01 || b == 0x02) {
    178            long areaOffset =byteArrayToLong(readBytes(offset+1,3)); 
    179        //   if(areaOffset == 0)
    180        //       return "未知";
    181        //   else
    182                return readString(areaOffset);
    183        } else
    184            return readString(offset);
    185    }
    186    /**
    187    * 通过ip位置获取国家地区,
    188    * 参照纯真ip数据库结构
    189    * @param offset
    190    * @return 国家+地区
    191    */
    192    private String seekCountryArea(long offset) {
    193            try {
    194            ipFile.seek(offset + 4);
    195            byte b = ipFile.readByte();
    196            if(b == AREA_FOLLOWED) 
    197            {
    198                long countryOffset = byteArrayToLong(readBytes(3));
    199                ipFile.seek(countryOffset);
    200                b = ipFile.readByte();
    201                if(b == NO_AREA) {
    202                    country = readString(byteArrayToLong(readBytes(3)));
    203                    ipFile.seek(countryOffset + 4);
    204                } else
    205                    country = readString(countryOffset);
    206                //area = readArea(ipFile.getFilePointer());
    207            } else if(b == NO_AREA) {
    208                country = readString(byteArrayToLong(readBytes(3)));
    209               // area = readArea(offset + 8);       
    210            } else {
    211                country = readString(ipFile.getFilePointer() - 1);
    212                //area = readArea(ipFile.getFilePointer());
    213            }
    214            return readText(country,"省(.+?)市");//+" "+area;
    215        } catch (IOException e) {
    216            return null;
    217        }
    218    }
    219    
    220    /**  
    221     * 正则表达式解析数据
    222     * @param result  
    223     * @identifier  
    224     * @return  
    225     */  
    226    public static String readText(String result, String identifier) {   
    227        Pattern shopNumberPattern = Pattern.compile(identifier);   
    228        Matcher shopNamMatcher = shopNumberPattern.matcher(result);   
    229        if (shopNamMatcher.find())   
    230            return shopNamMatcher.group(1);   
    231        return "";   
    232    } 
    233 
    234    /**
    235    * 从offset偏移处读取一个以0结束的字符串
    236    * @param offset
    237    * @return ret 读取的字符串,出错返回空字符串
    238    */
    239    private String readString(long offset){
    240        try {
    241            ipFile.seek(offset);
    242            byte[] b = new byte[128];
    243            int i;
    244            for(i=0; (b.length != i) && ((b[i]=ipFile.readByte()) != 0); i++);
    245            String ret = new String(b, 0 , i/*, "GBK"*/);
    246            ret = ret.trim();
    247            return (ret.equals("") ||
    248                           ret.indexOf("CZ88.NET") != -1 )?"未知":ret;
    249        } catch (IOException e) {
    250            System.out.println("读取文件失败_readString");
    251        }
    252        return "";
    253    }
    254 
    255    /**
    256    * 包含字符串的ip记录
    257    * @param addr 地址
    258    * @return IpRecord ip记录
    259    */
    260    
    261    public ArrayList<IpRecord> stringToIp(String addr) {
    262        ArrayList<IpRecord> ret = new ArrayList<IpRecord>();
    263        try{
    264            FileChannel fc = ipFile.getChannel();
    265            MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, ipFile.length());
    266            mbb.order(ByteOrder.LITTLE_ENDIAN);
    267            //上面3代码未使用,内存映射文件功能未写
    268 
    269            for(long i = ipBegin+4; i != ipEnd+4; i += RECORD_LENGTH) {
    270                String sca = seekCountryArea(byteArrayToLong(readBytes(i, 3)));       
    271                if(sca.indexOf(addr) != -1) {
    272                    IpRecord rec = new IpRecord();
    273                    rec.address = sca;
    274                    rec.beginIp= byteArrayToStringIp(readBytes(i-4,4));
    275                    rec.endIp= byteArrayToStringIp(readBytes(i+3,4));
    276                    ret.add(rec);
    277                } 
    278            }
    279        } catch (IOException e) {
    280            System.out.println(e.getMessage());
    281        }
    282        return ret;
    283    }
    284 
    285    /**
    286    * 封装ip记录,包括开始ip,结束ip和地址
    287    */
    288    private class IpRecord {
    289        public String beginIp;
    290        public String endIp;
    291        public String address;
    292 
    293        public IpRecord() {
    294            beginIp = endIp = address = "";   
    295        }
    296 
    297        public String toString() {
    298            return beginIp + " - " + endIp + " " + address;
    299        }
    300    }
    301 
    302    /**
    303    * @return 单一实例
    304    */
    305    public static IpAddress getInstance() {
    306        return instance;
    307    }
    308 
    309    /**
    310    * @param ip
    311    * @return ret
    312    */
    313    public String IpStringToAddress(String ip) {
    314        //这里要添加ip格式判断
    315        //public boolean isIP(Strin ip)
    316        long ipOffset = seekIp(ip);
    317        String ret = seekCountryArea(ipOffset);
    318        return ret;
    319    }
    320 
    321    /**
    322    * @return IpSum
    323    */
    324    public long getIpSum() {
    325        return ipSum;
    326    }
    327 
    328    public static void main(String[] args) throws UnknownHostException {
    329        IpAddress ipAddr = IpAddress.getInstance();
    330        //ip总数
    331        long l = ipAddr.getIpSum();
    332        System.out.println(l);
    333        //纯真ip数据更新时间
    334        String str = ipAddr.IpStringToAddress("255.255.255.0");
    335        System.out.println(str);
    336        
    337        //测试
    338        str = ipAddr.IpStringToAddress("222.88.59.214");
    339        System.out.println(str);
    340        str = ipAddr.IpStringToAddress("222.248.70.78");
    341        System.out.println(str);
    342        str = ipAddr.IpStringToAddress("188.1.255.255");
    343        System.out.println(str);
    344        str = ipAddr.IpStringToAddress("220.168.59.166");
    345        System.out.println(str);
    346        str = ipAddr.IpStringToAddress("221.10.61.90");
    347        System.out.println(str);
    348        InetAddress inet = InetAddress.getLocalHost(); 
    349        System.out.println("本机的ip=" + inet.getHostAddress()); 
    350    /*   java.net.InetAddress addr = null;
    351        try{
    352            addr = java.net.InetAddress.getLocalHost();
    353        }catch(java.net.UnknownHostException e){
    354            e.printStackTrace();
    355        }
    356        String ip=addr.getHostAddress().toString();//获得本机IP
    357        System.out.print(ip);
    358        String address=addr.getHostName().toString();//获得本机名称
    359        System.out.print(address);
    360        str = ipAddr.IpStringToAddress(ip);
    361        System.out.println(str);*/
    362 
    363 
    364        ArrayList<IpRecord> al = ipAddr.stringToIp("网吧");
    365        Iterator it = al.iterator();
    366 
    367        File f = new File("ipdata.txt");
    368        try{
    369        if(!f.exists()) {
    370            f.createNewFile();
    371        }
    372        BufferedWriter out = new BufferedWriter(
    373                new OutputStreamWriter(
    374                    new FileOutputStream(f, true)
    375                    )
    376                );
    377        int i=0;
    378        while(it.hasNext()) {
    379            out.write(it.next().toString());
    380            out.newLine();
    381            i++;
    382        }
    383        out.write(new Date().toString());
    384        out.write("总共搜索到 "+i);
    385        out.close();
    386        }catch(IOException e){
    387            e.printStackTrace();
    388        }
    389 
    390    }   
    391 } 

    自己在网上在去下载个qqwry.dat放到根目录下就好

  • 相关阅读:
    设计手稿: 搜索引擎
    软件版本介绍
    VS2012中使用编译的Qt-5.1.1静态库开发程序
    POJ2236(并查集)
    Java关键字this的用法总结
    paip.提升用户体验-----c++ gcc 命令在notepad++扩展中的配置..
    MySQL基本查询语句练习
    [置顶] 提升代码内外部质量的22条经验
    mysql 数据库复制表 create table city1 like city;
    两个脚本
  • 原文地址:https://www.cnblogs.com/yys369/p/3397075.html
Copyright © 2011-2022 走看看