DAT format access code
IPv6 access code:
import java.io.IOException;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
public class Ip {
private Map<Long, Long> prefStart = new HashMap<>();
private Map<Long, Long> prefEnd = new HashMap<>();
private BigInteger[] endArr;
private String[] addrArr;
private static Ip instance = null;
private Ip(String filePath) throws IOException {
Path path = Paths.get(filePath);
byte[] data = null;
try {
data = Files.readAllBytes(path);
} catch (IOException e) {
throw new IOException("file not found" + e);
}
long numbers = unpackInt4byte(data[4], data[5], data[6], data[7]);
for (int k = 0; k < numbers; k++) {
int i = k * 12 + 4 + 4;
prefStart.put(unpackInt4byte(data[i + 8], data[i + 9], data[i + 10], data[i + 11]), unpackInt4byte(data[i], data[i + 1], data[i + 2], data[i + 3]));
prefEnd.put(unpackInt4byte(data[i + 8], data[i + 9], data[i + 10], data[i + 11]), unpackInt4byte(data[i + 4], data[i + 5], data[i + 6], data[i + 7]));
}
int recordSize = (int) unpackInt4byte(data[0], data[1], data[2], data[3]);
endArr = new BigInteger[recordSize];
addrArr = new String[recordSize];
for (int i = 0; i < recordSize; i++) {
int p = (int) numbers * 12 + 4 + 4 + (i * 55);
// long endipnum = unpackInt4byte(data[p+50], data[1 + p+50], data[2 + p+50], data[3 + p+50]);
int offset = (int) unpackInt4byte(data[50 + p], data[50 + p + 1], data[50 + p + 2], data[50 + p + 3]);
int length = data[50 + p + 4] & 0xff;
BigInteger endipnum = new BigInteger(new String(Arrays.copyOfRange(data, p, p + 50)).replaceAll("\\*", ""));
endArr[i] = endipnum;
addrArr[i] = new String(Arrays.copyOfRange(data, offset, (offset + length)));
}
}
public static synchronized Ip getInstance(String path) throws IOException {
if (instance == null)
instance = new Ip(path);
return instance;
}
public String get(String ip) {
try {
InetAddress inetAddress = InetAddress.getByName(ip);
if (!(inetAddress instanceof Inet6Address)) {
throw new IllegalArgumentException("Not an IPv6 address: " + ip);
}
ip = inetAddress.getHostAddress();
} catch (Exception e) {
throw new IllegalArgumentException("Invalid IPv6 address: " + ip, e);
}
if (ip.contains("%")) {
ip = ip.split("%")[0];
}
String[] ips = ip.split("\\:");
long pref = Long.parseLong(ips[0], 16);
BigInteger val = stringToBigInt(ip);
if (prefStart.get(pref) == null || prefEnd.get(pref) == null) {
return "保留|保留|||||||||||||||||";
}
long low = prefStart.get(pref), high = prefEnd.get(pref);
long cur = low == high ? low : search(low, high, val);
return addrArr[(int) cur];
}
private int search(long low, long high, BigInteger k) {
int M = 0;
while (low <= high) {
int mid = (int) (low + high) / 2;
BigInteger endipNum = endArr[mid];
if (endipNum.compareTo(k) == 0 || endipNum.compareTo(k) == 1) {
M = mid;
if (mid == 0) {
break;
}
high = mid - 1;
} else
low = mid + 1;
}
return M;
}
private long unpackInt4byte(byte a, byte b, byte c, byte d) {
return (a & 0xFFL) | ((b << 8) & 0xFF00L) | ((c << 16) & 0xFF0000L) | ((d << 24) & 0xFF000000L);
}
public static BigInteger stringToBigInt(String ipInString) {
ipInString = ipInString.replace(" ", "");
byte[] bytes = ipv6ToBytes(ipInString);
return new BigInteger(bytes);
}
public static byte[] ipv6ToBytes(String ipv6) {
try {
// 去除可能的区域索引(如fe80::1%eth0 -> fe80::1)
String pureIpv6 = ipv6.split("%")[0];
// 使用InetAddress解析
InetAddress inetAddress = InetAddress.getByName(pureIpv6);
if (!(inetAddress instanceof Inet6Address)) {
throw new IllegalArgumentException("Not an IPv6 address: " + ipv6);
}
// 直接返回16字节的地址
return inetAddress.getAddress();
} catch (UnknownHostException e) {
throw new IllegalArgumentException("Invalid IPv6 address: " + ipv6, e);
}
}
public static void main(String[] args) throws IOException {
Ip ip = Ip.getInstance("D:\\databases\\ipv6_city.dat");
System.out.println(ip.get("240e:437:cb70:1650:5428:792c:bf57:932d%0"));
}
}Last updated

