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放到根目录下就好