import java.io.*;

public class IPParser {
	private String DbPath = "D:\\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 {
		
		long initUsedMemory = ( Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() ) ;
		
		long start = System.currentTimeMillis();
		
		IPParser w = new IPParser();
		// w.setPath(new File("QQWry2.Dat").getAbsolutePath());
		w.seek("125.10.100.17");
		System.out.println(w.getCountry() + " " + w.getLocal());
		
		long end = System.currentTimeMillis();
		
		long endUsedMemory = ( Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory() ) ;
		
		System.out.println("time spent:"+ ( end - start ) + " ns" );
		System.out.println("memory consumes:" + ( endUsedMemory - initUsedMemory ) );
		
	}

}
最近下载更多
1358849392  LV21 4月12日
微信网友_6166561027215360  LV2 2022年10月8日
仰望星空five  LV1 2020年3月13日
skipple3  LV39 2020年3月3日
yang9999  LV1 2019年12月20日
lgp1991  LV1 2019年5月7日
快乐的男孩子  LV5 2019年1月23日
caohanren  LV11 2019年1月17日
Silence丶二哈  LV13 2019年1月16日
tian2019  LV1 2019年1月10日
最近浏览更多
1358849392  LV21 4月12日
ming_123_9715  LV23 2022年12月15日
wanglun_wl  LV10 2022年10月18日
微信网友_6166561027215360  LV2 2022年10月8日
funcrit  LV2 2022年7月18日
zhy1989wz  LV6 2022年3月15日
农村拓哉 2021年12月7日
暂无贡献等级
13561143836  LV7 2021年11月10日
明天更美好  LV10 2021年9月9日
铁血战士  LV1 2021年6月2日
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友