作者:じ☆ve宝贝
发布时间:2016-02-19T16:26:11
使用纯真ip的qqwry.dat作为库来验证ip地址的具体位置信息
package cn.studyjava;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
public final class IPParser {
private static final String DATA_PATH = "cn/studyjava/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("125.34.19.135", ", "));
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");
}
}