依星源码资源网,依星资源网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

【好消息,好消息,好消息】VIP会员可以发表文章赚积分啦 !
查看: 24|回复: 0

用java程序来读取纯真ip数据库

[复制链接] 主动推送

1万

主题

1万

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
12008
发表于 7 天前 | 显示全部楼层 |阅读模式
用java程序来读取纯真ip数据库
  1. package info.frady;  
  2.   
  3. /** *
  4. * 一条IP范围记录,不仅包括国家和区域,也包括起始IP和结束IP *  

  5. *  
  6. * @author swallow */  
  7. public class IPEntry {  
  8.     public String beginIp;  
  9.     public String endIp;  
  10.     public String country;  
  11.     public String area;  
  12.       
  13.     /**
  14.      * 构造函数
  15.      */  
  16.      
  17.    
  18.   
  19. public IPEntry() {  
  20.         beginIp = endIp = country = area = "";  
  21.     }  
  22.       
  23.     public String toString(){  
  24.        return      this.area+"  "+this.country+"IP范围:"+this.beginIp+"-"+this.endIp;  
  25.     }  
  26.    }   
复制代码
  1. package info.frady;  
  2.   
  3. /*
  4. * Created on 2004-8-4
  5. *
  6. */  
  7.   
  8.   
  9. import java.io.UnsupportedEncodingException;  
  10.   
  11. /**
  12. * @author LJ-silver
  13. */  
  14. public class Utils {  
  15.     /**
  16.      * 从ip的字符串形式得到字节数组形式
  17.      * @param ip 字符串形式的ip
  18.      * @return 字节数组形式的ip
  19.      */  
  20.     public static byte[] getIpByteArrayFromString(String ip) {  
  21.         byte[] ret = new byte[4];  
  22.         java.util.StringTokenizer st = new java.util.StringTokenizer(ip, ".");  
  23.         try {  
  24.             ret[0] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
  25.             ret[1] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
  26.             ret[2] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
  27.             ret[3] = (byte)(Integer.parseInt(st.nextToken()) & 0xFF);  
  28.         } catch (Exception e) {  
  29.             System.out.println(e.getMessage());  
  30.         }  
  31.         return ret;  
  32.     }  
  33.       
  34.     public static void main(String args[]){  
  35.          byte[] a=getIpByteArrayFromString(args[0]);  
  36.           for(int i=0;i< a.length;i++)  
  37.                 System.out.println(a[i]);  
  38.           System.out.println(getIpStringFromBytes(a));   
  39.     }  
  40.     /**
  41.      * 对原始字符串进行编码转换,如果失败,返回原始的字符串
  42.      * @param s 原始字符串
  43.      * @param srcEncoding 源编码方式
  44.      * @param destEncoding 目标编码方式
  45.      * @return 转换编码后的字符串,失败返回原始字符串
  46.      */  
  47.     public static String getString(String s, String srcEncoding, String destEncoding) {  
  48.         try {  
  49.             return new String(s.getBytes(srcEncoding), destEncoding);  
  50.         } catch (UnsupportedEncodingException e) {  
  51.             return s;  
  52.         }  
  53.     }  
  54.       
  55.     /**
  56.      * 根据某种编码方式将字节数组转换成字符串
  57.      * @param b 字节数组
  58.      * @param encoding 编码方式
  59.      * @return 如果encoding不支持,返回一个缺省编码的字符串
  60.      */  
  61.     public static String getString(byte[] b, String encoding) {  
  62.         try {  
  63.             return new String(b, encoding);  
  64.         } catch (UnsupportedEncodingException e) {  
  65.             return new String(b);  
  66.         }  
  67.     }  
  68.       
  69.     /**
  70.      * 根据某种编码方式将字节数组转换成字符串
  71.      * @param b 字节数组
  72.      * @param offset 要转换的起始位置
  73.      * @param len 要转换的长度
  74.      * @param encoding 编码方式
  75.      * @return 如果encoding不支持,返回一个缺省编码的字符串
  76.      */  
  77.     public static String getString(byte[] b, int offset, int len, String encoding) {  
  78.         try {  
  79.             return new String(b, offset, len, encoding);  
  80.         } catch (UnsupportedEncodingException e) {  
  81.             return new String(b, offset, len);  
  82.         }  
  83.     }  
  84.       
  85.     /**
  86.      * @param ip ip的字节数组形式
  87.      * @return 字符串形式的ip
  88.      */  
  89.     public static String getIpStringFromBytes(byte[] ip) {  
  90.         StringBuffer sb = new StringBuffer();  
  91.         sb.append(ip[0] & 0xFF);  
  92.         sb.append('.');         
  93.         sb.append(ip[1] & 0xFF);  
  94.         sb.append('.');         
  95.         sb.append(ip[2] & 0xFF);  
  96.         sb.append('.');         
  97.         sb.append(ip[3] & 0xFF);  
  98.         return sb.toString();  
  99.     }  
  100.   
  101. }   
复制代码
  1. package info.frady;  
  2.   
  3. /*
  4. * LumaQQ - Java QQ Client
  5. *
  6. * Copyright (C) 2004 luma < stubma@163.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21. */  
  22.   
  23.   
  24.   
  25. import java.io.FileNotFoundException;  
  26. import java.io.IOException;  
  27. import java.io.RandomAccessFile;  
  28. import java.nio.ByteOrder;  
  29. import java.nio.MappedByteBuffer;  
  30. import java.nio.channels.FileChannel;  
  31. import java.util.ArrayList;  
  32. import java.util.Hashtable;  
  33. import java.util.List;  
  34.   
  35.   
  36.   
  37.   
  38. /**
  39. *  * 用来读取QQwry.dat文件,以根据ip获得好友位置,QQwry.dat的格式是
  40. * 一. 文件头,共8字节
  41. *        1. 第一个起始IP的绝对偏移, 4字节
  42. *     2. 最后一个起始IP的绝对偏移, 4字节
  43. * 二. "结束地址/国家/区域"记录区
  44. *     四字节ip地址后跟的每一条记录分成两个部分
  45. *     1. 国家记录
  46. *     2. 地区记录
  47. *     但是地区记录是不一定有的。而且国家记录和地区记录都有两种形式
  48. *     1. 以0结束的字符串
  49. *     2. 4个字节,一个字节可能为0x1或0x2
  50. *           a. 为0x1时,表示在绝对偏移后还跟着一个区域的记录,注意是绝对偏移之后,而不是这四个字节之后
  51. *        b. 为0x2时,表示在绝对偏移后没有区域记录
  52. *        不管为0x1还是0x2,后三个字节都是实际国家名的文件内绝对偏移
  53. *           如果是地区记录,0x1和0x2的含义不明,但是如果出现这两个字节,也肯定是跟着3个字节偏移,如果不是
  54. *        则为0结尾字符串
  55. * 三. "起始地址/结束地址偏移"记录区
  56. *     1. 每条记录7字节,按照起始地址从小到大排列
  57. *        a. 起始IP地址,4字节
  58. *        b. 结束ip地址的绝对偏移,3字节
  59. *
  60. * 注意,这个文件里的ip地址和所有的偏移量均采用little-endian格式,而java是采用
  61. * big-endian格式的,要注意转换
  62. *  
  63. *
  64. * @author 马若劼
  65. */  
  66. public class IPSeeker {  
  67.     /**
  68.      *      * 用来封装ip相关信息,目前只有两个字段,ip所在的国家和地区
  69.      *  
  70.      *
  71.      * @author swallow     */  
  72.     private class IPLocation {  
  73.         public String country;  
  74.         public String area;  
  75.   
  76.         public IPLocation() {  
  77.             country = area = "";  
  78.         }  
  79.   
  80.         public IPLocation getCopy() {  
  81.             IPLocation ret = new IPLocation();  
  82.             ret.country = country;  
  83.             ret.area = area;  
  84.             return ret;  
  85.         }  
  86.     }  
  87.   
  88.     private static final String IP_FILE = IPSeeker.class.getResource("/QQWry.dat").toString().substring(5);  
  89.   
  90.     // 一些固定常量,比如记录长度等等  
  91.     private static final int IP_RECORD_LENGTH = 7;  
  92.     private static final byte AREA_FOLLOWED = 0x01;  
  93.     private static final byte NO_AREA = 0x2;  
  94.   
  95.      // 用来做为cache,查询一个ip时首先查看cache,以减少不必要的重复查找  
  96.     private Hashtable ipCache;  
  97.     // 随机文件访问类  
  98.     private RandomAccessFile ipFile;  
  99.     // 内存映射文件  
  100.     private MappedByteBuffer mbb;  
  101.     // 单一模式实例  
  102.     private static IPSeeker instance = new IPSeeker();  
  103.     // 起始地区的开始和结束的绝对偏移  
  104.     private long ipBegin, ipEnd;  
  105.     // 为提高效率而采用的临时变量  
  106.     private IPLocation loc;  
  107.     private byte[] buf;  
  108.     private byte[] b4;  
  109.     private byte[] b3;  
  110.   
  111.     /**
  112.      * 私有构造函数
  113.      */  
  114.     private IPSeeker()  {  
  115.         ipCache = new Hashtable();  
  116.         loc = new IPLocation();  
  117.         buf = new byte[100];  
  118.         b4 = new byte[4];  
  119.         b3 = new byte[3];  
  120.         try {  
  121.             ipFile = new RandomAccessFile(IP_FILE, "r");  
  122.         } catch (FileNotFoundException e) {  
  123.                         System.out.println(IPSeeker.class.getResource("/QQWry.dat").toString());  
  124.                         System.out.println(IP_FILE);  
  125.             System.out.println("IP地址信息文件没有找到,IP显示功能将无法使用");  
  126.             ipFile = null;  
  127.   
  128.         }  
  129.         // 如果打开文件成功,读取文件头信息  
  130.         if(ipFile != null) {  
  131.             try {  
  132.                 ipBegin = readLong4(0);  
  133.                 ipEnd = readLong4(4);  
  134.                 if(ipBegin == -1 || ipEnd == -1) {  
  135.                     ipFile.close();  
  136.                     ipFile = null;  
  137.                 }  
  138.             } catch (IOException e) {  
  139.                 System.out.println("IP地址信息文件格式有错误,IP显示功能将无法使用");  
  140.                 ipFile = null;  
  141.             }  
  142.         }  
  143.     }  
  144.   
  145.     /**
  146.      * @return 单一实例
  147.      */  
  148.     public static IPSeeker getInstance() {  
  149.         return instance;  
  150.     }  
  151.   
  152.     /**
  153.      * 给定一个地点的不完全名字,得到一系列包含s子串的IP范围记录
  154.      * @param s 地点子串
  155.      * @return 包含IPEntry类型的List
  156.      */  
  157.     public List getIPEntriesDebug(String s) {  
  158.         List ret = new ArrayList();  
  159.         long endOffset = ipEnd + 4;  
  160.         for(long offset = ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {  
  161.             // 读取结束IP偏移  
  162.             long temp = readLong3(offset);  
  163.             // 如果temp不等于-1,读取IP的地点信息  
  164.             if(temp != -1) {  
  165.                 IPLocation loc = getIPLocation(temp);  
  166.                 // 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续  
  167.                 if(loc.country.indexOf(s) != -1 || loc.area.indexOf(s) != -1) {  
  168.                     IPEntry entry = new IPEntry();  
  169.                     entry.country = loc.country;  
  170.                     entry.area = loc.area;  
  171.                     // 得到起始IP  
  172.                     readIP(offset - 4, b4);  
  173.                     entry.beginIp = Utils.getIpStringFromBytes(b4);  
  174.                     // 得到结束IP  
  175.                     readIP(temp, b4);  
  176.                     entry.endIp = Utils.getIpStringFromBytes(b4);  
  177.                     // 添加该记录  
  178.                     ret.add(entry);  
  179.                 }  
  180.             }  
  181.         }  
  182.         return ret;  
  183.     }  
  184.   
  185.     /**
  186.      * 给定一个地点的不完全名字,得到一系列包含s子串的IP范围记录
  187.      * @param s 地点子串
  188.      * @return 包含IPEntry类型的List
  189.      */  
  190.     public List getIPEntries(String s) {  
  191.         List ret = new ArrayList();  
  192.         try {  
  193.             // 映射IP信息文件到内存中  
  194.             if(mbb == null) {  
  195.                 FileChannel fc = ipFile.getChannel();  
  196.                 mbb = fc.map(FileChannel.MapMode.READ_ONLY, 0, ipFile.length());  
  197.                 mbb.order(ByteOrder.LITTLE_ENDIAN);  
  198.             }  
  199.   
  200.             int endOffset = (int)ipEnd;  
  201.             for(int offset = (int)ipBegin + 4; offset <= endOffset; offset += IP_RECORD_LENGTH) {  
  202.                 int temp = readInt3(offset);  
  203.                 if(temp != -1) {  
  204.                     IPLocation loc = getIPLocation(temp);  
  205.                     // 判断是否这个地点里面包含了s子串,如果包含了,添加这个记录到List中,如果没有,继续  
  206.                     if(loc.country.indexOf(s) != -1 || loc.area.indexOf(s) != -1) {  
  207.                         IPEntry entry = new IPEntry();  
  208.                         entry.country = loc.country;  
  209.                         entry.area = loc.area;  
  210.                         // 得到起始IP  
  211.                         readIP(offset - 4, b4);  
  212.                         entry.beginIp = Utils.getIpStringFromBytes(b4);  
  213.                         // 得到结束IP  
  214.                         readIP(temp, b4);  
  215.                         entry.endIp = Utils.getIpStringFromBytes(b4);  
  216.                         // 添加该记录  
  217.                         ret.add(entry);  
  218.                     }  
  219.                 }  
  220.             }  
  221.         } catch (IOException e) {  
  222.             System.out.println(e.getMessage());  
  223.         }  
  224.         return ret;  
  225.     }  
  226.   
  227.     /**
  228.      * 从内存映射文件的offset位置开始的3个字节读取一个int
  229.      * @param offset
  230.      * @return
  231.      */  
  232.     private int readInt3(int offset) {  
  233.         mbb.position(offset);  
  234.         return mbb.getInt() & 0x00FFFFFF;  
  235.     }  
  236.   
  237.     /**
  238.      * 从内存映射文件的当前位置开始的3个字节读取一个int
  239.      * @return
  240.      */  
  241.     private int readInt3() {  
  242.         return mbb.getInt() & 0x00FFFFFF;  
  243.     }  
  244.   
  245.     /**
  246.      * 根据IP得到国家名
  247.      * @param ip ip的字节数组形式
  248.      * @return 国家名字符串
  249.      */  
  250.     public String getCountry(byte[] ip) {  
  251.         // 检查ip地址文件是否正常  
  252.         if(ipFile == null) return "错误的IP数据库文件";  
  253.         // 保存ip,转换ip字节数组为字符串形式  
  254.         String ipStr = Utils.getIpStringFromBytes(ip);  
  255.         // 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件  
  256.         if(ipCache.containsKey(ipStr)) {  
  257.             IPLocation loc = (IPLocation)ipCache.get(ipStr);  
  258.             return loc.country;  
  259.         } else {  
  260.             IPLocation loc = getIPLocation(ip);  
  261.             ipCache.put(ipStr, loc.getCopy());  
  262.             return loc.country;  
  263.         }  
  264.     }  
  265.   
  266.     /**
  267.      * 根据IP得到国家名
  268.      * @param ip IP的字符串形式
  269.      * @return 国家名字符串
  270.      */  
  271.     public String getCountry(String ip) {  
  272.         return getCountry(Utils.getIpByteArrayFromString(ip));  
  273.     }  
  274.   
  275.     /**
  276.      * 根据IP得到地区名
  277.      * @param ip ip的字节数组形式
  278.      * @return 地区名字符串
  279.      */  
  280.     public String getArea(byte[] ip) {  
  281.         // 检查ip地址文件是否正常  
  282.         if(ipFile == null) return "错误的IP数据库文件";  
  283.         // 保存ip,转换ip字节数组为字符串形式  
  284.         String ipStr = Utils.getIpStringFromBytes(ip);  
  285.         // 先检查cache中是否已经包含有这个ip的结果,没有再搜索文件  
  286.         if(ipCache.containsKey(ipStr)) {  
  287.             IPLocation loc = (IPLocation)ipCache.get(ipStr);  
  288.             return loc.area;  
  289.         } else {  
  290.             IPLocation loc = getIPLocation(ip);  
  291.             ipCache.put(ipStr, loc.getCopy());  
  292.             return loc.area;  
  293.         }  
  294.     }  
  295.   
  296.     /**
  297.      * 根据IP得到地区名
  298.      * @param ip IP的字符串形式
  299.      * @return 地区名字符串
  300.      */  
  301.     public String getArea(String ip) {  
  302.         return getArea(Utils.getIpByteArrayFromString(ip));  
  303.     }  
  304.   
  305.     /**
  306.      * 根据ip搜索ip信息文件,得到IPLocation结构,所搜索的ip参数从类成员ip中得到
  307.      * @param ip 要查询的IP
  308.      * @return IPLocation结构
  309.      */  
  310.     private IPLocation getIPLocation(byte[] ip) {  
  311.         IPLocation info = null;  
  312.         long offset = locateIP(ip);  
  313.         if(offset != -1)  
  314.             info = getIPLocation(offset);  
  315.         if(info == null) {  
  316.             info = new IPLocation();  
  317.             info.country = "未知国家";  
  318.             info.area = "未知地区";  
  319.         }  
  320.         return info;  
  321.     }  
  322.   
  323.     /**
  324.      * 从offset位置读取4个字节为一个long,因为java为big-endian格式,所以没办法
  325.      * 用了这么一个函数来做转换
  326.      * @param offset
  327.      * @return 读取的long值,返回-1表示读取文件失败
  328.      */  
  329.     private long readLong4(long offset) {  
  330.         long ret = 0;  
  331.         try {  
  332.             ipFile.seek(offset);  
  333.             ret |= (ipFile.readByte() & 0xFF);  
  334.             ret |= ((ipFile.readByte() << 8) & 0xFF00);  
  335.             ret |= ((ipFile.readByte() << 16) & 0xFF0000);  
  336.             ret |= ((ipFile.readByte() << 24) & 0xFF000000);  
  337.             return ret;  
  338.         } catch (IOException e) {  
  339.             return -1;  
  340.         }  
  341.     }  
  342.   
  343.     /**
  344.      * 从offset位置读取3个字节为一个long,因为java为big-endian格式,所以没办法
  345.      * 用了这么一个函数来做转换
  346.      * @param offset
  347.      * @return 读取的long值,返回-1表示读取文件失败
  348.      */  
  349.     private long readLong3(long offset) {  
  350.         long ret = 0;  
  351.         try {  
  352.             ipFile.seek(offset);  
  353.             ipFile.readFully(b3);  
  354.             ret |= (b3[0] & 0xFF);  
  355.             ret |= ((b3[1] << 8) & 0xFF00);  
  356.             ret |= ((b3[2] << 16) & 0xFF0000);  
  357.             return ret;  
  358.         } catch (IOException e) {  
  359.             return -1;  
  360.         }  
  361.     }  
  362.   
  363.     /**
  364.      * 从当前位置读取3个字节转换成long
  365.      * @return
  366.      */  
  367.     private long readLong3() {  
  368.         long ret = 0;  
  369.         try {  
  370.             ipFile.readFully(b3);  
  371.             ret |= (b3[0] & 0xFF);  
  372.             ret |= ((b3[1] << 8) & 0xFF00);  
  373.             ret |= ((b3[2] << 16) & 0xFF0000);  
  374.             return ret;  
  375.         } catch (IOException e) {  
  376.             return -1;  
  377.         }  
  378.     }  
  379.   
  380.     /**
  381.      * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是
  382.      * 文件中是little-endian形式,将会进行转换
  383.      * @param offset
  384.      * @param ip
  385.      */  
  386.     private void readIP(long offset, byte[] ip) {  
  387.         try {  
  388.             ipFile.seek(offset);  
  389.             ipFile.readFully(ip);  
  390.             byte temp = ip[0];  
  391.             ip[0] = ip[3];  
  392.             ip[3] = temp;  
  393.             temp = ip[1];  
  394.             ip[1] = ip[2];  
  395.             ip[2] = temp;  
  396.         } catch (IOException e) {  
  397.             System.out.println(e.getMessage());  
  398.         }  
  399.     }  
  400.   
  401.     /**
  402.      * 从offset位置读取四个字节的ip地址放入ip数组中,读取后的ip为big-endian格式,但是
  403.      * 文件中是little-endian形式,将会进行转换
  404.      * @param offset
  405.      * @param ip
  406.      */  
  407.     private void readIP(int offset, byte[] ip) {  
  408.         mbb.position(offset);  
  409.         mbb.get(ip);  
  410.         byte temp = ip[0];  
  411.         ip[0] = ip[3];  
  412.         ip[3] = temp;  
  413.         temp = ip[1];  
  414.         ip[1] = ip[2];  
  415.         ip[2] = temp;  
  416.     }  
  417.   
  418.     /**
  419.      * 把类成员ip和beginIp比较,注意这个beginIp是big-endian的
  420.      * @param ip 要查询的IP
  421.      * @param beginIp 和被查询IP相比较的IP
  422.      * @return 相等返回0,ip大于beginIp则返回1,小于返回-1。
  423.      */  
  424.     private int compareIP(byte[] ip, byte[] beginIp) {  
  425.         for(int i = 0; i < 4; i++) {  
  426.             int r = compareByte(ip[i], beginIp[i]);  
  427.             if(r != 0)  
  428.                 return r;  
  429.         }  
  430.         return 0;  
  431.     }  
  432.   
  433.     /**
  434.      * 把两个byte当作无符号数进行比较
  435.      * @param b1
  436.      * @param b2
  437.      * @return 若b1大于b2则返回1,相等返回0,小于返回-1
  438.      */  
  439.     private int compareByte(byte b1, byte b2) {  
  440.         if((b1 & 0xFF) > (b2 & 0xFF)) // 比较是否大于  
  441.             return 1;  
  442.         else if((b1 ^ b2) == 0)// 判断是否相等  
  443.             return 0;  
  444.         else  
  445.             return -1;  
  446.     }  
  447.   
  448.     /**
  449.      * 这个方法将根据ip的内容,定位到包含这个ip国家地区的记录处,返回一个绝对偏移
  450.      * 方法使用二分法查找。
  451.      * @param ip 要查询的IP
  452.      * @return 如果找到了,返回结束IP的偏移,如果没有找到,返回-1
  453.      */  
  454.     private long locateIP(byte[] ip) {  
  455.         long m = 0;  
  456.         int r;  
  457.         // 比较第一个ip项  
  458.         readIP(ipBegin, b4);  
  459.         r = compareIP(ip, b4);  
  460.         if(r == 0) return ipBegin;  
  461.         else if(r < 0) return -1;  
  462.         // 开始二分搜索  
  463.         for(long i = ipBegin, j = ipEnd; i < j; ) {  
  464.             m = getMiddleOffset(i, j);  
  465.             readIP(m, b4);  
  466.             r = compareIP(ip, b4);  
  467.             // log.debug(Utils.getIpStringFromBytes(b));  
  468.             if(r > 0)  
  469.                 i = m;  
  470.             else if(r < 0) {  
  471.                 if(m == j) {  
  472.                     j -= IP_RECORD_LENGTH;  
  473.                     m = j;  
  474.                 } else  
  475.                     j = m;  
  476.             } else  
  477.                 return readLong3(m + 4);  
  478.         }  
  479.         // 如果循环结束了,那么i和j必定是相等的,这个记录为最可能的记录,但是并非  
  480.         //     肯定就是,还要检查一下,如果是,就返回结束地址区的绝对偏移  
  481.         m = readLong3(m + 4);  
  482.         readIP(m, b4);  
  483.         r = compareIP(ip, b4);  
  484.         if(r <= 0) return m;  
  485.         else return -1;  
  486.     }  
  487.   
  488.     /**
  489.      * 得到begin偏移和end偏移中间位置记录的偏移
  490.      * @param begin
  491.      * @param end
  492.      * @return
  493.      */  
  494.     private long getMiddleOffset(long begin, long end) {  
  495.         long records = (end - begin) / IP_RECORD_LENGTH;  
  496.         records >>= 1;  
  497.         if(records == 0) records = 1;  
  498.         return begin + records * IP_RECORD_LENGTH;  
  499.     }  
  500.   
  501.     /**
  502.      * 给定一个ip国家地区记录的偏移,返回一个IPLocation结构
  503.      * @param offset
  504.      * @return
  505.      */  
  506.     private IPLocation getIPLocation(long offset) {  
  507.         try {  
  508.             // 跳过4字节ip  
  509.             ipFile.seek(offset + 4);  
  510.             // 读取第一个字节判断是否标志字节  
  511.             byte b = ipFile.readByte();  
  512.             if(b == AREA_FOLLOWED) {  
  513.                 // 读取国家偏移  
  514.                 long countryOffset = readLong3();  
  515.                 // 跳转至偏移处  
  516.                 ipFile.seek(countryOffset);  
  517.                 // 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向  
  518.                 b = ipFile.readByte();  
  519.                 if(b == NO_AREA) {  
  520.                     loc.country = readString(readLong3());  
  521.                     ipFile.seek(countryOffset + 4);  
  522.                 } else  
  523.                     loc.country = readString(countryOffset);  
  524.                 // 读取地区标志  
  525.                 loc.area = readArea(ipFile.getFilePointer());  
  526.             } else if(b == NO_AREA) {  
  527.                 loc.country = readString(readLong3());  
  528.                 loc.area = readArea(offset + 8);  
  529.             } else {  
  530.                 loc.country = readString(ipFile.getFilePointer() - 1);  
  531.                 loc.area = readArea(ipFile.getFilePointer());  
  532.             }  
  533.             return loc;  
  534.         } catch (IOException e) {  
  535.             return null;  
  536.         }  
  537.     }  
  538.   
  539.     /**
  540.      * @param offset
  541.      * @return
  542.      */  
  543.     private IPLocation getIPLocation(int offset) {  
  544.         // 跳过4字节ip  
  545.         mbb.position(offset + 4);  
  546.         // 读取第一个字节判断是否标志字节  
  547.         byte b = mbb.get();  
  548.         if(b == AREA_FOLLOWED) {  
  549.             // 读取国家偏移  
  550.             int countryOffset = readInt3();  
  551.             // 跳转至偏移处  
  552.             mbb.position(countryOffset);  
  553.             // 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向  
  554.             b = mbb.get();  
  555.             if(b == NO_AREA) {  
  556.                 loc.country = readString(readInt3());  
  557.                 mbb.position(countryOffset + 4);  
  558.             } else  
  559.                 loc.country = readString(countryOffset);  
  560.             // 读取地区标志  
  561.             loc.area = readArea(mbb.position());  
  562.         } else if(b == NO_AREA) {  
  563.             loc.country = readString(readInt3());  
  564.             loc.area = readArea(offset + 8);  
  565.         } else {  
  566.             loc.country = readString(mbb.position() - 1);  
  567.             loc.area = readArea(mbb.position());  
  568.         }  
  569.         return loc;  
  570.     }  
  571.   
  572.     /**
  573.      * 从offset偏移开始解析后面的字节,读出一个地区名
  574.      * @param offset
  575.      * @return 地区名字符串
  576.      * @throws IOException
  577.      */  
  578.     private String readArea(long offset) throws IOException {  
  579.         ipFile.seek(offset);  
  580.         byte b = ipFile.readByte();  
  581.         if(b == 0x01 || b == 0x02) {  
  582.             long areaOffset = readLong3(offset + 1);  
  583.             if(areaOffset == 0)  
  584.                 return "未知地区";  
  585.             else  
  586.                 return readString(areaOffset);  
  587.         } else  
  588.             return readString(offset);  
  589.     }  
  590.   
  591.     /**
  592.      * @param offset
  593.      * @return
  594.      */  
  595.     private String readArea(int offset) {  
  596.         mbb.position(offset);  
  597.         byte b = mbb.get();  
  598.         if(b == 0x01 || b == 0x02) {  
  599.             int areaOffset = readInt3();  
  600.             if(areaOffset == 0)  
  601.                 return "未知地区";  
  602.             else  
  603.                 return readString(areaOffset);  
  604.         } else  
  605.             return readString(offset);  
  606.     }  
  607.   
  608.     /**
  609.      * 从offset偏移处读取一个以0结束的字符串
  610.      * @param offset
  611.      * @return 读取的字符串,出错返回空字符串
  612.      */  
  613.     private String readString(long offset) {  
  614.         try {  
  615.             ipFile.seek(offset);  
  616.             int i;  
  617.             for(i = 0, buf[i] = ipFile.readByte(); buf[i] != 0; buf[++i] = ipFile.readByte());  
  618.             if(i != 0)  
  619.                 return Utils.getString(buf, 0, i, "GBK");  
  620.         } catch (IOException e) {  
  621.             System.out.println(e.getMessage());  
  622.         }  
  623.         return "";  
  624.     }  
  625.   
  626.     /**
  627.      * 从内存映射文件的offset位置得到一个0结尾字符串
  628.      * @param offset
  629.      * @return
  630.      */  
  631.     private String readString(int offset) {  
  632.         try {  
  633.             mbb.position(offset);  
  634.             int i;  
  635.             for(i = 0, buf[i] = mbb.get(); buf[i] != 0; buf[++i] = mbb.get());  
  636.             if(i != 0)  
  637.                 return Utils.getString(buf, 0, i, "GBK");  
  638.         } catch (IllegalArgumentException e) {  
  639.             System.out.println(e.getMessage());  
  640.         }  
  641.         return "";  
  642.     }  
  643.   
  644.     public String getAddress(String ip){  
  645.         String country = getCountry(ip).equals(" CZ88.NET")?"":getCountry(ip);  
  646.         String area = getArea(ip).equals(" CZ88.NET")?"":getArea(ip);  
  647.         String address = country+" "+area;  
  648.         return address.trim();  
  649.     }  
  650. }   
复制代码
下面是一段测试程序
  1. package info.frady;  
  2.   
  3. public class Iptest {  
  4.   
  5.     /**
  6.      * @param args
  7.      */  
  8.     public static void main(String[] args) {  
  9.         IPSeeker is=IPSeeker.getInstance();  
  10.         String testIp="122.70.146.60";  
  11.         System.out.print(is.getAddress(testIp));  
  12.         System.out.print(is.getArea(testIp));  
  13.          
  14.     }  
  15.   
  16. }  
复制代码


相关帖子

扫码关注微信公众号,及时获取最新资源信息!下载附件优惠VIP会员5折;永久VIP免费
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明:
1、本站提供的所有资源仅供参考学习使用,版权归原著所有,禁止下载本站资源参与商业和非法行为,请在24小时之内自行删除!
2、本站所有内容均由互联网收集整理、网友上传,并且以计算机技术研究交流为目的,仅供大家参考、学习,请勿任何商业目的与商业用途。
3、若您需要商业运营或用于其他商业活动,请您购买正版授权并合法使用。
4、论坛的所有内容都不保证其准确性,完整性,有效性,由于源码具有复制性,一经售出,概不退换。阅读本站内容因误导等因素而造成的损失本站不承担连带责任。
5、用户使用本网站必须遵守适用的法律法规,对于用户违法使用本站非法运营而引起的一切责任,由用户自行承担
6、本站所有资源来自互联网转载,版权归原著所有,用户访问和使用本站的条件是必须接受本站“免责声明”,如果不遵守,请勿访问或使用本网站
7、本站使用者因为违反本声明的规定而触犯中华人民共和国法律的,一切后果自己负责,本站不承担任何责任。
8、凡以任何方式登陆本网站或直接、间接使用本网站资料者,视为自愿接受本网站声明的约束。
9、本站以《2013 中华人民共和国计算机软件保护条例》第二章 “软件著作权” 第十七条为原则:为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。若有学员需要商用本站资源,请务必联系版权方购买正版授权!
10、本网站如无意中侵犯了某个企业或个人的知识产权,请来信【站长信箱312337667@qq.com】告之,本站将立即删除。
郑重声明:
本站所有资源仅供用户本地电脑学习源代码的内含设计思想和原理,禁止任何其他用途!
本站所有资源、教程来自互联网转载,仅供学习交流,不得商业运营资源,不确保资源完整性,图片和资源仅供参考,不提供任何技术服务。
本站资源仅供本地编辑研究学习参考,禁止未经资源商正版授权参与任何商业行为,违法行为!如需商业请购买各资源商正版授权
本站仅收集资源,提供用户自学研究使用,本站不存在私自接受协助用户架设游戏或资源,非法运营资源行为。
 
在线客服
点击这里给我发消息 点击这里给我发消息 点击这里给我发消息
售前咨询热线
312337667

微信扫一扫,私享最新原创实用干货

QQ|免责声明|小黑屋|依星资源网 ( 鲁ICP备2021043233号-3 )|网站地图

GMT+8, 2024-11-23 23:09

Powered by Net188.com X3.4

邮箱:312337667@qq.com 客服QQ:312337667(工作时间:9:00~21:00)

快速回复 返回顶部 返回列表