diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..7f3b587 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,6 @@ +# Default ignored files +/shelf/ +/workspace.xml + + + diff --git a/IP.java b/IP.java deleted file mode 100644 index 548f0ed..0000000 --- a/IP.java +++ /dev/null @@ -1,143 +0,0 @@ -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.locks.ReentrantLock; - -class IP { - - public static void main(String[] args){ - IP.load("H:\\loveapp\\codebase\\17mon\\17monipdb.dat"); - - System.out.println(Arrays.toString(IP.find("8.8.8.8"))); - System.out.println(Arrays.toString(IP.find("255.255.255.255"))); - } - - public static boolean enableFileWatch = false; - - private static int offset; - private static int[] index = new int[256]; - private static ByteBuffer dataBuffer; - private static ByteBuffer indexBuffer; - private static Long lastModifyTime = 0L; - private static File ipFile ; - private static ReentrantLock lock = new ReentrantLock(); - - public static void load(String filename) { - ipFile = new File(filename); - load(); - if (enableFileWatch) { - watch(); - } - } - - public static String[] find(String ip) { - int ip_prefix_value = new Integer(ip.substring(0, ip.indexOf("."))); - long ip2long_value = ip2long(ip); - int start = index[ip_prefix_value]; - int max_comp_len = offset - 1028; - long index_offset = -1; - int index_length = -1; - byte b = 0; - for (start = start * 8 + 1024; start < max_comp_len; start += 8) { - if (int2long(indexBuffer.getInt(start)) >= ip2long_value) { - index_offset = bytesToLong(b, indexBuffer.get(start + 6), indexBuffer.get(start + 5), indexBuffer.get(start + 4)); - index_length = 0xFF & indexBuffer.get(start + 7); - break; - } - } - - byte[] areaBytes; - lock.lock(); - try { - dataBuffer.position(offset + (int) index_offset - 1024); - areaBytes = new byte[index_length]; - dataBuffer.get(areaBytes, 0, index_length); - } finally { - lock.unlock(); - } - - return new String(areaBytes).split("\t"); - } - - private static void watch() { - Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() { - @Override - public void run() { - long time = ipFile.lastModified(); - if (time > lastModifyTime) { - lastModifyTime = time; - load(); - } - } - }, 1000L, 5000L, TimeUnit.MILLISECONDS); - } - - private static void load() { - lastModifyTime = ipFile.lastModified(); - FileInputStream fin = null; - lock.lock(); - try { - dataBuffer = ByteBuffer.allocate(Long.valueOf(ipFile.length()).intValue()); - fin = new FileInputStream(ipFile); - int readBytesLength; - byte[] chunk = new byte[4096]; - while (fin.available() > 0) { - readBytesLength = fin.read(chunk); - dataBuffer.put(chunk, 0, readBytesLength); - } - dataBuffer.position(0); - int indexLength = dataBuffer.getInt(); - byte[] indexBytes = new byte[indexLength]; - dataBuffer.get(indexBytes, 0, indexLength - 4); - indexBuffer = ByteBuffer.wrap(indexBytes); - indexBuffer.order(ByteOrder.LITTLE_ENDIAN); - offset = indexLength; - - int loop = 0; - while (loop++ < 256) { - index[loop - 1] = indexBuffer.getInt(); - } - indexBuffer.order(ByteOrder.BIG_ENDIAN); - } catch (IOException ioe) { - - } finally { - try { - if (fin != null) { - fin.close(); - } - } catch (IOException e){} - lock.unlock(); - } - } - - private static long bytesToLong(byte a, byte b, byte c, byte d) { - return int2long((((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff))); - } - - private static int str2Ip(String ip) { - String[] ss = ip.split("\\."); - int a, b, c, d; - a = Integer.parseInt(ss[0]); - b = Integer.parseInt(ss[1]); - c = Integer.parseInt(ss[2]); - d = Integer.parseInt(ss[3]); - return (a << 24) | (b << 16) | (c << 8) | d; - } - - private static long ip2long(String ip) { - return int2long(str2Ip(ip)); - } - - private static long int2long(int i) { - long l = i & 0x7fffffffL; - if (i < 0) { - l |= 0x080000000L; - } - return l; - } -} \ No newline at end of file diff --git a/README.md b/README.md index 65a91ed..6671c90 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ -java -==== +# General Info -17mon IP库解析代码 +This project includes a brief summary of code review in a Java repository forked +from a GitHub public repository. +This code was developed 7 years ago and includes a base code in Java version 4 that +works in J2SE 1.4. +As part of our project, we will be focusing on features of clean code: +1. Documentation: Repository being old has no underlying description. Project demands + navigation through class to understand its purpose. We will be adding comments and + documentation for enhanced readability. +2. Refactor: Base code requires immense refactoring to include good coding practices. + Issues of naming conventions (meaningful names), refactoring methods (functions), + formatting and error handling will be closed. -##基本用法 -```java -IP.enableFileWatch = true; // 默认值为:false,如果为true将会检查ip库文件的变化自动reload数据 + -IP.load("IP库本地绝对路径"); - -IP.find("8.8.8.8");//返回字符串数组["GOOGLE","GOOGLE"] - -``` - -IPExt的用法与IP的用法相同,只是用来解析datx格式文件。 \ No newline at end of file diff --git a/README_author.md b/README_author.md new file mode 100644 index 0000000..65a91ed --- /dev/null +++ b/README_author.md @@ -0,0 +1,17 @@ +java +==== + +17mon IP库解析代码 + +##基本用法 +```java + +IP.enableFileWatch = true; // 默认值为:false,如果为true将会检查ip库文件的变化自动reload数据 + +IP.load("IP库本地绝对路径"); + +IP.find("8.8.8.8");//返回字符串数组["GOOGLE","GOOGLE"] + +``` + +IPExt的用法与IP的用法相同,只是用来解析datx格式文件。 \ No newline at end of file diff --git a/Readme_translation.md b/Readme_translation.md new file mode 100644 index 0000000..e37875e --- /dev/null +++ b/Readme_translation.md @@ -0,0 +1,8 @@ +IP.enableFileWatch = true; // The default value is: false, if it is true, it will check the changes of the ip library file and automatically reload the data + +IP.load("The local absolute path of the IP library"); + +IP.find("8.8.8.8");//Returns an array of strings ["GOOGLE","GOOGLE"] + + +The usage of IPExt is the same as that of IP, but it is used to parse datx format files. diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..5e431df --- /dev/null +++ b/pom.xml @@ -0,0 +1,30 @@ + + + 4.0.0 + + org.example + CodeReading + 1.0-SNAPSHOT + + + junit + junit + 4.12 + test + + + org.junit.jupiter + junit-jupiter-api + 5.7.2 + test + + + + + 8 + 8 + + + \ No newline at end of file diff --git a/src/main/java/Constants.java b/src/main/java/Constants.java new file mode 100644 index 0000000..3a5d6cd --- /dev/null +++ b/src/main/java/Constants.java @@ -0,0 +1,6 @@ + + +public class Constants { + public static final String IP_ADDRESS = "213.255.193.25"; + public static boolean enableFileWatch = false; +} diff --git a/src/main/java/IP.java b/src/main/java/IP.java new file mode 100644 index 0000000..61ec3b1 --- /dev/null +++ b/src/main/java/IP.java @@ -0,0 +1,293 @@ + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantLock; + + +class IP +{ + + private static int offset; + private static int[] index = new int[256]; + private static ByteBuffer dataBuffer; + private static ByteBuffer indexBuffer; + private static Long lastModifyTime = 0L; + private static File ipFile; + private static ReentrantLock lock = new ReentrantLock(); + private static List iplist = new ArrayList(); + + + + public static void main(String[] args) + { + IP geoIp=new IP(); + geoIp.load("./src/main/resources/17monipdb.dat"); + System.out.println("find:"+Arrays.toString(IP.find(Constants.IP_ADDRESS))); + + } + + + + public void load(String filename) + { + try { + ipFile = new File(filename); + load(); + if (Constants.enableFileWatch) { + watch(); + } + }catch(Exception e) + { + e.printStackTrace(); + } + } + + public static String[] find(String ip) + { + int ip_prefix_value = new Integer(ip.substring(0, ip.indexOf("."))); + long ip2long_value = ip2long(ip); + int start = index[ip_prefix_value]; + int max_comp_len = offset - 1028; + long index_offset = -1; + int index_length = -1; + byte byteCount = 0; + byte[] areaBytes; + for (start = start * 8 + 1024; start < max_comp_len; start += 8) + { + if (int2long(indexBuffer.getInt(start)) >= ip2long_value) + { + index_offset = bytesToLong(byteCount, indexBuffer.get(start + 6), + indexBuffer.get(start + 5), + indexBuffer.get(start + 4)); + index_length = 0xFF & indexBuffer.get(start + 7); + break; + } + } + lock.lock(); + try + { + dataBuffer.position(offset + (int) index_offset - 1024); + areaBytes = new byte[index_length]; + dataBuffer.get(areaBytes, 0, index_length); + } + finally + { + lock.unlock(); + } + + return new String(areaBytes).split("\t"); + } + + + + + public static String[] find2(String ip) + { + String[] area = null; + long ip2long_value = ip2long(ip); + + IpBean ipBean = new IpBean(); + ipBean.startip = ip2long_value; + + int len = iplist.size()-1; + + int idx = len / 2; + int high = len; + int low = 0; + + while (low <= high) + { + IpBean tempIPBean = iplist.get(idx); + int compare = tempIPBean.compareTo(ipBean); + if (compare < 0) + { + low = idx+1; + } + else if (compare > 0) + { + high = idx-1; + } + else + { + area = tempIPBean.area; + break; + } + idx =(low+high)/2; + } + + return area; + } + + private static void watch() + { + Executors.newScheduledThreadPool(1).scheduleAtFixedRate(new Runnable() + { + @Override + public void run() + { + long time = ipFile.lastModified(); + if (time > lastModifyTime) + { + lastModifyTime = time; + load(); + } + } + }, 1000L, 5000L, TimeUnit.MILLISECONDS); + } + + private static void load2() + { + iplist.clear(); + int start = index[0]; + int max_comp_len = offset - 1028; + long index_offset = -1; + int index_length = -1; + byte b = 0; + + IpBean lastip = null; + for (start = start * 8 + 1024; start < max_comp_len; start += 8) + { + long startipl = int2long(indexBuffer.getInt(start)); + index_offset = bytesToLong(b, indexBuffer.get(start + 6), + indexBuffer.get(start + 5), + indexBuffer.get(start + 4)); + index_length = 0xFF & indexBuffer.get(start + 7); + + byte[] areaBytes; + lock.lock(); + try + { + dataBuffer.position(offset + (int) index_offset - 1024); + areaBytes = new byte[index_length]; + dataBuffer.get(areaBytes, 0, index_length); + + IpBean ipb = new IpBean(); + ipb.endip = startipl; + ipb.area = new String(areaBytes).split("\t"); + + if (lastip != null) + { + if (Arrays.equals(ipb.area, lastip.area)) + { + lastip.endip = ipb.endip; + } + else + { + ipb.startip = lastip.endip+1; + iplist.add(ipb); + lastip = ipb; + } + } + else + { + ipb.startip = 0; + lastip = ipb; + } + } + finally + { + lock.unlock(); + } + } + } + + public static void load() + { + lastModifyTime = ipFile.lastModified(); + FileInputStream fin = null; + lock.lock(); + try + { + dataBuffer = ByteBuffer.allocate(Long.valueOf(ipFile.length()) + .intValue()); + fin = new FileInputStream(ipFile); + int readBytesLength; + byte[] chunk = new byte[4096]; + while (fin.available() > 0) + { + readBytesLength = fin.read(chunk); + dataBuffer.put(chunk, 0, readBytesLength); + } + dataBuffer.position(0); + int indexLength = dataBuffer.getInt(); + byte[] indexBytes = new byte[indexLength]; + dataBuffer.get(indexBytes, 0, indexLength - 4); + indexBuffer = ByteBuffer.wrap(indexBytes); + indexBuffer.order(ByteOrder.LITTLE_ENDIAN); + offset = indexLength; + + int loop = 0; + while (loop++ < 256) + { + index[loop - 1] = indexBuffer.getInt(); + } + indexBuffer.order(ByteOrder.BIG_ENDIAN); + } + catch (IOException ioe) + { + ioe.printStackTrace(); + + } + finally + { + try + { + if (fin != null) + { + fin.close(); + } + } + catch (IOException e) + { + e.printStackTrace(); + } + lock.unlock(); + } + load2(); + } + + private static long bytesToLong(byte a, byte b, byte c, byte d) + { + return int2long((((a & 0xff) << 24) | ((b & 0xff) << 16) + | ((c & 0xff) << 8) | (d & 0xff))); + } + + private static int str2Ip(String ip) + { + String[] splitIP = ip.split("\\."); + int a, b, c, d; + a = Integer.parseInt(splitIP[0]); + b = Integer.parseInt(splitIP[1]); + c = Integer.parseInt(splitIP[2]); + d = Integer.parseInt(splitIP[3]); + return (a << 24) | (b << 16) | (c << 8) | d; + } + + private static long ip2long(String ip) + { + return int2long(str2Ip(ip)); + } + + private static long int2long(int i) + { + long l = i & 0x7fffffffL; + if (i < 0) + { + l |= 0x080000000L; + } + return l; + } + + + + + +} \ No newline at end of file diff --git a/IPExt.java b/src/main/java/IPExt.java similarity index 98% rename from IPExt.java rename to src/main/java/IPExt.java index e0de74e..9b71c28 100644 --- a/IPExt.java +++ b/src/main/java/IPExt.java @@ -10,7 +10,7 @@ public class IPExt { public static void main(String[] args) { - IPExt.load("H:\\loveapp\\codebase\\17mon\\17monipdb.datx"); + IPExt.load("./17monipdb.datx"); System.out.println(Arrays.toString(IPExt.find("8.8.8.8"))); System.out.println(Arrays.toString(IPExt.find("118.28.8.8"))); diff --git a/src/main/java/IpBean.java b/src/main/java/IpBean.java new file mode 100644 index 0000000..94af511 --- /dev/null +++ b/src/main/java/IpBean.java @@ -0,0 +1,19 @@ +public class IpBean implements Comparable +{ + long startip; + long endip; + String[] area; + + @Override + public int compareTo(IpBean otherBean) + { + if (otherBean.startip < startip || otherBean.startip > endip) { + if (startip > otherBean.startip) { + return 1; + } else if (startip < otherBean.startip) { + return -1; + } + } + return 0; + } +} diff --git a/src/main/resources/17monipdb.dat b/src/main/resources/17monipdb.dat new file mode 100644 index 0000000..c947aba Binary files /dev/null and b/src/main/resources/17monipdb.dat differ diff --git a/src/test/java/IpBeanTest.java b/src/test/java/IpBeanTest.java new file mode 100644 index 0000000..1d3147d --- /dev/null +++ b/src/test/java/IpBeanTest.java @@ -0,0 +1,39 @@ +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import static org.junit.jupiter.api.Assertions.*; + +class IpBeanTest { + IP ipTesT=new IP(); + +/* IP Addresses to test returned Geo location + UK - 193.62.157.66 + USA - 162.254.206.227 + India - 1.23.255.255 + */ + + @Test + public void testIPLoad_UK_IP() { + ipTesT.load("./src/main/resources/17monipdb.dat"); + + //Output translation - [United Kingdom, United Kingdom] + assertEquals("[英国, 英国]", Arrays.toString(IP.find("193.62.157.66"))); // Default value used by author + assertEquals("[英国, 英国]", Arrays.toString(IP.find("213.255.193.25"))); + } + @Test + public void testIPLoad_US_IP() { + //Output translation - [America America] + assertEquals("[美国, 美国]", Arrays.toString(IP.find("162.254.206.227"))); + + } + @Test + public void testIPLoad_India_IP() { + //Outpur translation - [India, India] + assertEquals("[印度, 印度]", Arrays.toString(IP.find("1.23.255.255"))); + + } + } + +/* Transalations are done via Google Translator */ + +