IP庫的查詢

做了一段時間的數據統計功能,無論是apache,還是tomcat,在記錄日誌的過程中都有IP被記錄,目前大多數軟件的後臺都要求統計一下,數據的來源是從哪些城市過來的,所以要用到IP庫。以前一直以爲這個東西一定是購買的,後來在網上終於找到了免費的,還是還位仁兄特意寫了java的代碼用來參考!在些表示感謝!
轉載地址:
http://www.blogjava.net/alvin/archive/2007/08/23/141139.html

import java.io.*;

public class QQWry {
private String DbPath = "D:\\Downloads\\IPLook\\QQWry.Dat" + ""; // 純真IP數據庫地址

private String Country, LocalStr;

private long IPN;

private int RecordCount, CountryFlag;

private long RangE, RangB, OffSet, StartIP, EndIP, FirstStartIP,
LastStartIP, EndIPOff;

private RandomAccessFile fis;

private byte[] buff;

private long B2L(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 ipToInt(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;
}

public void seek(String ip) throws Exception {
this.IPN = ipToInt(ip);
fis = new RandomAccessFile(this.DbPath, "r");
buff = new byte[4];
fis.seek(0);
fis.read(buff);
FirstStartIP = this.B2L(buff);
fis.read(buff);
LastStartIP = this.B2L(buff);
RecordCount = (int) ((LastStartIP - FirstStartIP) / 7);
if (RecordCount <= 1) {
LocalStr = Country = "未知";
throw new Exception();
}

RangB = 0;
RangE = RecordCount;
long RecNo;

do {
RecNo = (RangB + RangE) / 2;
getStartIP(RecNo);
if (IPN == StartIP) {
RangB = RecNo;
break;
}
if (IPN > StartIP)
RangB = RecNo;
else
RangE = RecNo;
} while (RangB < RangE - 1);

getStartIP(RangB);
getEndIP();
getCountry(IPN);

fis.close();
}

private String getFlagStr(long OffSet) throws IOException {
int flag = 0;
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.B2L(buff);
} else
break;
} while (true);

if (OffSet < 12) {
return "";
} else {
fis.seek(OffSet);
return getStr();
}
}

private String getStr() throws IOException {
long l = fis.length();
ByteArrayOutputStream byteout = new ByteArrayOutputStream();
byte c = fis.readByte();
do {
byteout.write(c);
c = fis.readByte();
} while (c != 0 && fis.getFilePointer() < l);
return byteout.toString();
}

private void getCountry(long ip) throws IOException {
if (CountryFlag == 1 || CountryFlag == 2) {
Country = getFlagStr(EndIPOff + 4);
if (CountryFlag == 1) {
LocalStr = getFlagStr(fis.getFilePointer());
if (IPN >= ipToInt("255.255.255.0")
&& IPN <= ipToInt("255.255.255.255")) {
LocalStr = getFlagStr(EndIPOff + 21);
Country = getFlagStr(EndIPOff + 12);
}
} else {
LocalStr = getFlagStr(EndIPOff + 8);
}
} else {
Country = getFlagStr(EndIPOff + 4);
LocalStr = getFlagStr(fis.getFilePointer());
}
}

private long getEndIP() throws IOException {
fis.seek(EndIPOff);
buff = new byte[4];
fis.read(buff);
EndIP = this.B2L(buff);
buff = new byte[1];
fis.read(buff);
CountryFlag = (buff[0] < 0) ? 256 + buff[0] : buff[0];
return EndIP;
}

private long getStartIP(long RecNo) throws IOException {
OffSet = FirstStartIP + RecNo * 7;
fis.seek(OffSet);
buff = new byte[4];
fis.read(buff);
StartIP = this.B2L(buff);
buff = new byte[3];
fis.read(buff);
EndIPOff = this.B2L(buff);
return StartIP;
}

public String getLocal() {
return this.LocalStr;
}

public String getCountry() {
return this.Country;
}

public void setPath(String path) {
this.DbPath = path;
}

public static void main(String[] args) throws Exception {
QQWry w = new QQWry();
// w.setPath(new File("QQWry2.Dat").getAbsolutePath());
w.seek("219.232.233.103");
System.out.println(w.getCountry() + " " + w.getLocal());
}

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章