diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6eb3c6e4d..01d3940d6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,7 +3,7 @@
-------------------------------------------------------------------------------------------------------------
-# 5.4.1 (2020-08-20)
+# 5.4.1 (2020-08-24)
### 新特性
* 【core 】 StrUtil增加firstNonXXX方法(issue#1020@Github)
@@ -14,6 +14,7 @@
* 【core 】 增加PathUtil和FileNameUtil,分离FileUtil中部分方法
* 【core 】 改造IndexedComparator,增加InstanceComparator
* 【extra 】 增加CglibUtil
+* 【extra 】 增加Ipv4Util(pr#161@Gitee)
### Bug修复#
* 【poi 】 修复ExcelBase.isXlsx方法判断问题(issue#I1S502@Gitee)
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java
index d16397b69..b5ec8e720 100644
--- a/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/Ipv4Util.java
@@ -1,440 +1,327 @@
package cn.hutool.core.net;
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
/**
- * IP地址工具类
+ * IPV4地址工具类
+ *
+ *
pr自:https://gitee.com/loolly/hutool/pulls/161
*
* @author ZhuKun
- * @date 2020-08-21
+ * @since 5.4.1
*/
public class Ipv4Util {
- /**
- * IP段的分割符
- */
- public static final String IP_SPLIT_MARK = "-";
+ /**
+ * IP段的分割符
+ */
+ public static final String IP_SPLIT_MARK = "-";
- /**
- * IP与掩码的分割符
- */
- public static final String IP_MASK_SPLIT_MARK = "/";
+ /**
+ * IP与掩码的分割符
+ */
+ public static final String IP_MASK_SPLIT_MARK = "/";
- /**
- * 最大掩码位
- */
- public static final int IP_MASK_MAX = 32;
+ /**
+ * 最大掩码位
+ */
+ public static final int IP_MASK_MAX = 32;
- /**
- * 格式化IP段
- *
- * @param ip IP地址
- * @param mask 掩码
- * @return 返回xxx.xxx.xxx.xxx/mask的格式
- */
- public static String formatIpBlock(String ip, String mask) {
- return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask);
- }
+ /**
+ * 格式化IP段
+ *
+ * @param ip IP地址
+ * @param mask 掩码
+ * @return 返回xxx.xxx.xxx.xxx/mask的格式
+ */
+ public static String formatIpBlock(String ip, String mask) {
+ return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask);
+ }
- /**
- * 智能转换IP地址集合
- *
- * @param ipRange IP段,支持X.X.X.X-X.X.X.X或X.X.X.X/X
- * @param isAll true:全量地址,false:可用地址;仅在ipRange为X.X.X.X/X时才生效
- * @return IP集
- */
- public static List list(String ipRange, boolean isAll) {
- if (ipRange.contains(IP_SPLIT_MARK)) {
- String[] range = ipRange.split(IP_SPLIT_MARK);
- return list(range[0], range[1]);
- } else if (ipRange.contains(IP_MASK_SPLIT_MARK)) {
- String[] param = ipRange.split(IP_MASK_SPLIT_MARK);
- return list(param[0], Integer.parseInt(param[1]), isAll);
- } else {
- List ips = new ArrayList<>();
- ips.add(ipRange);
- return ips;
- }
- }
+ /**
+ * 智能转换IP地址集合
+ *
+ * @param ipRange IP段,支持X.X.X.X-X.X.X.X或X.X.X.X/X
+ * @param isAll true:全量地址,false:可用地址;仅在ipRange为X.X.X.X/X时才生效
+ * @return IP集
+ */
+ public static List list(String ipRange, boolean isAll) {
+ if (ipRange.contains(IP_SPLIT_MARK)) {
+ String[] range = ipRange.split(IP_SPLIT_MARK);
+ return list(range[0], range[1]);
+ } else if (ipRange.contains(IP_MASK_SPLIT_MARK)) {
+ String[] param = ipRange.split(IP_MASK_SPLIT_MARK);
+ return list(param[0], Integer.parseInt(param[1]), isAll);
+ } else {
+ List ips = new ArrayList<>();
+ ips.add(ipRange);
+ return ips;
+ }
+ }
- /**
- * 根据IP地址、子网掩码获取IP地址区间
- *
- * @param ip IP地址
- * @param maskBit 掩码位,例如24、32
- * @param isAll true:全量地址,false:可用地址
- * @return
- */
- public static List list(String ip, int maskBit, boolean isAll) {
- List list = new ArrayList<>();
- if (maskBit == IP_MASK_MAX) {
- if (Boolean.TRUE.equals(isAll)) {
- list.add(ip);
- }
- } else {
- String startIp = getBeginIpStr(ip, maskBit);
- String endIp = getEndIpStr(ip, maskBit);
- String subStart = startIp.split("\\.")[0] + "." + startIp.split("\\.")[1] + "." + startIp.split("\\.")[2] + ".";
- String subEnd = endIp.split("\\.")[0] + "." + endIp.split("\\.")[1] + "." + endIp.split("\\.")[2] + ".";
- if (Boolean.TRUE.equals(isAll)) {
- startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]));
- endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]));
- } else {
- startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]) + 1);
- endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]) - 1);
- }
- list = list(startIp, endIp);
- }
- return list;
- }
+ /**
+ * 根据IP地址、子网掩码获取IP地址区间
+ *
+ * @param ip IP地址
+ * @param maskBit 掩码位,例如24、32
+ * @param isAll true:全量地址,false:可用地址
+ * @return 区间地址
+ */
+ public static List list(String ip, int maskBit, boolean isAll) {
+ List list = new ArrayList<>();
+ if (maskBit == IP_MASK_MAX) {
+ if (Boolean.TRUE.equals(isAll)) {
+ list.add(ip);
+ }
+ } else {
+ String startIp = getBeginIpStr(ip, maskBit);
+ String endIp = getEndIpStr(ip, maskBit);
+ String subStart = startIp.split("\\.")[0] + "." + startIp.split("\\.")[1] + "." + startIp.split("\\.")[2] + ".";
+ String subEnd = endIp.split("\\.")[0] + "." + endIp.split("\\.")[1] + "." + endIp.split("\\.")[2] + ".";
+ if (Boolean.TRUE.equals(isAll)) {
+ startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]));
+ endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]));
+ } else {
+ startIp = subStart + (Integer.parseInt(startIp.split("\\.")[3]) + 1);
+ endIp = subEnd + (Integer.parseInt(endIp.split("\\.")[3]) - 1);
+ }
+ list = list(startIp, endIp);
+ }
+ return list;
+ }
- /**
- * 得到IP地址区间
- *
- * @param ipFrom 开始IP
- * @param ipTo 结束IP
- * @return
- */
- public static List list(String ipFrom, String ipTo) {
- List ips = new ArrayList<>();
- String[] ipfromd = ipFrom.split("\\.");
- String[] iptod = ipTo.split("\\.");
- int[] int_ipf = new int[4];
- int[] int_ipt = new int[4];
- for (int i = 0; i < 4; i++) {
- int_ipf[i] = Integer.parseInt(ipfromd[i]);
- int_ipt[i] = Integer.parseInt(iptod[i]);
- }
- for (int A = int_ipf[0]; A <= int_ipt[0]; A++) {
- for (int B = (A == int_ipf[0] ? int_ipf[1] : 0); B <= (A == int_ipt[0] ? int_ipt[1]
- : 255); B++) {
- for (int C = (B == int_ipf[1] ? int_ipf[2] : 0); C <= (B == int_ipt[1] ? int_ipt[2]
- : 255); C++) {
- for (int D = (C == int_ipf[2] ? int_ipf[3] : 0); D <= (C == int_ipt[2] ? int_ipt[3]
- : 255); D++) {
- ips.add(A + "." + B + "." + C + "." + D);
- }
- }
- }
- }
- return ips;
- }
+ /**
+ * 得到IP地址区间
+ *
+ * @param ipFrom 开始IP
+ * @param ipTo 结束IP
+ * @return 区间地址
+ */
+ public static List list(String ipFrom, String ipTo) {
+ final int[] ipf = Convert.convert(int[].class, StrUtil.splitToArray(ipFrom, '.'));
+ final int[] ipt = Convert.convert(int[].class, StrUtil.splitToArray(ipTo, '.'));
- /**
- * 把long类型的Ip转为一般Ip类型:xx.xx.xx.xx
- *
- * @param ip
- * @return
- */
- public static String longIpToStr(Long ip) {
- String s1 = String.valueOf((ip & 4278190080L) / 16777216L);
- String s2 = String.valueOf((ip & 16711680L) / 65536L);
- String s3 = String.valueOf((ip & 65280L) / 256L);
- String s4 = String.valueOf(ip & 255L);
- return s1 + "." + s2 + "." + s3 + "." + s4;
- }
+ final List ips = new ArrayList<>();
+ for (int a = ipf[0]; a <= ipt[0]; a++) {
+ for (int b = (a == ipf[0] ? ipf[1] : 0); b <= (a == ipt[0] ? ipt[1]
+ : 255); b++) {
+ for (int c = (b == ipf[1] ? ipf[2] : 0); c <= (b == ipt[1] ? ipt[2]
+ : 255); c++) {
+ for (int d = (c == ipf[2] ? ipf[3] : 0); d <= (c == ipt[2] ? ipt[3]
+ : 255); d++) {
+ ips.add(a + "." + b + "." + c + "." + d);
+ }
+ }
+ }
+ }
+ return ips;
+ }
- /**
- * 把xxx.xxx.xxx.xxx类型的转为long类型的IP
- *
- * @param ip 字符类型的IP
- * @return
- */
- public static Long strIpToLong(String ip) {
- Long ipLong = 0L;
- String ipTemp = ip;
- ipLong = ipLong * 256
- + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf(".")));
- ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1);
- ipLong = ipLong * 256
- + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf(".")));
- ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1);
- ipLong = ipLong * 256
- + Long.parseLong(ipTemp.substring(0, ipTemp.indexOf(".")));
- ipTemp = ipTemp.substring(ipTemp.indexOf(".") + 1);
- ipLong = ipLong * 256 + Long.parseLong(ipTemp);
- return ipLong;
- }
+ /**
+ * 根据long值获取ip v4地址:xx.xx.xx.xx
+ *
+ * @param longIP IP的long表示形式
+ * @return IP V4 地址
+ */
+ public static String longToIpv4(long longIP) {
+ final StringBuilder sb = StrUtil.builder();
+ // 直接右移24位
+ sb.append((longIP >>> 24));
+ sb.append(".");
+ // 将高8位置0,然后右移16位
+ sb.append(((longIP & 0x00FFFFFF) >>> 16));
+ sb.append(".");
+ sb.append(((longIP & 0x0000FFFF) >>> 8));
+ sb.append(".");
+ sb.append((longIP & 0x000000FF));
+ return sb.toString();
+ }
- /**
- * 根据掩码位获取掩码
- *
- * @param maskBit 掩码位数,如"28"、"30"
- * @return
- */
- public static String getMaskByMaskBit(String maskBit) {
- return StrUtil.isEmpty(maskBit) ? "error, maskBit is null !"
- : maskBitMap().get(maskBit);
- }
+ /**
+ * 根据ip地址(xxx.xxx.xxx.xxx)计算出long型的数据
+ *
+ * @param strIP IP V4 地址
+ * @return long值
+ */
+ public static long ipv4ToLong(String strIP) {
+ if (Validator.isIpv4(strIP)) {
+ long[] ip = new long[4];
+ // 先找到IP地址字符串中.的位置
+ int position1 = strIP.indexOf(".");
+ int position2 = strIP.indexOf(".", position1 + 1);
+ int position3 = strIP.indexOf(".", position2 + 1);
+ // 将每个.之间的字符串转换成整型
+ ip[0] = Long.parseLong(strIP.substring(0, position1));
+ ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2));
+ ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3));
+ ip[3] = Long.parseLong(strIP.substring(position3 + 1));
+ return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
+ }
+ return 0;
+ }
- /**
- * 根据 ip/掩码位 计算IP段的起始IP(字符串型)
- *
- * @param ip 给定的IP,如218.240.38.69
- * @param maskBit 给定的掩码位,如30
- * @return 起始IP的字符串表示
- */
- public static String getBeginIpStr(String ip, int maskBit) {
- return longIpToStr(getBeginIpLong(ip, maskBit));
- }
+ /**
+ * 根据 ip/掩码位 计算IP段的起始IP(字符串型)
+ *
+ * @param ip 给定的IP,如218.240.38.69
+ * @param maskBit 给定的掩码位,如30
+ * @return 起始IP的字符串表示
+ */
+ public static String getBeginIpStr(String ip, int maskBit) {
+ return longToIpv4(getBeginIpLong(ip, maskBit));
+ }
- /**
- * 根据 ip/掩码位 计算IP段的起始IP(Long型)
- *
- * @param ip 给定的IP,如218.240.38.69
- * @param maskBit 给定的掩码位,如30
- * @return 起始IP的长整型表示
- */
- private static Long getBeginIpLong(String ip, int maskBit) {
- return strIpToLong(ip) & strIpToLong(getMaskByMaskBit(maskBit));
- }
+ /**
+ * 根据 ip/掩码位 计算IP段的起始IP(Long型)
+ *
+ * @param ip 给定的IP,如218.240.38.69
+ * @param maskBit 给定的掩码位,如30
+ * @return 起始IP的长整型表示
+ */
+ private static Long getBeginIpLong(String ip, int maskBit) {
+ return ipv4ToLong(ip) & ipv4ToLong(getMaskByMaskBit(maskBit));
+ }
- /**
- * 根据 ip/掩码位 计算IP段的终止IP(字符串型)
- *
- * @param ip 给定的IP,如218.240.38.69
- * @param maskBit 给定的掩码位,如30
- * @return 终止IP的字符串表示
- */
- public static String getEndIpStr(String ip, int maskBit) {
- return longIpToStr(getEndIpLong(ip, maskBit));
- }
+ /**
+ * 根据 ip/掩码位 计算IP段的终止IP(字符串型)
+ *
+ * @param ip 给定的IP,如218.240.38.69
+ * @param maskBit 给定的掩码位,如30
+ * @return 终止IP的字符串表示
+ */
+ public static String getEndIpStr(String ip, int maskBit) {
+ return longToIpv4(getEndIpLong(ip, maskBit));
+ }
- /**
- * 根据 ip/掩码位 计算IP段的终止IP(Long型)
- * 注:此接口返回负数,请使用转成字符串后再转Long型
- *
- * @param ip 给定的IP,如218.240.38.69
- * @param maskBit 给定的掩码位,如30
- * @return 终止IP的长整型表示
- */
- private static Long getEndIpLong(String ip, int maskBit) {
- return getBeginIpLong(ip, maskBit)
- + ~strIpToLong(getMaskByMaskBit(maskBit));
- }
+ /**
+ * 根据子网掩码转换为掩码位
+ *
+ * @param mask 掩码,例如xxx.xxx.xxx.xxx
+ * @return 掩码位,例如32
+ */
+ public static int getMaskBitByMask(String mask) {
+ StringBuffer sbf;
+ String str;
+ int inetmask = 0;
+ int count;
+ for (String s : StrUtil.split(mask, ',')) {
+ sbf = toBin(Integer.parseInt(s));
+ str = sbf.reverse().toString();
+ count = 0;
+ for (int i = 0; i < str.length(); i++) {
+ i = str.indexOf('1', i);
+ if (i == -1) {
+ break;
+ }
+ count++;
+ }
+ inetmask += count;
+ }
+ return inetmask;
+ }
+ /**
+ * 计算子网大小
+ *
+ * @param maskBit 掩码位
+ * @param isAll true:全量地址,false:可用地址
+ * @return 地址总数
+ */
+ public static int countByMaskBit(int maskBit, boolean isAll) {
+ //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0
+ boolean isZero = !isAll && (maskBit <= 0 || maskBit >= 32);
+ if (isZero) {
+ return 0;
+ }
+ if (isAll) {
+ return (int) Math.pow(2, 32 - maskBit);
+ } else {
+ return (int) Math.pow(2, 32 - maskBit) - 2;
+ }
+ }
- /**
- * 根据子网掩码转换为掩码位
- *
- * @param mask 掩码,例如xxx.xxx.xxx.xxx
- * @return 掩码位,例如32
- */
- public static int getMaskBitByMask(String mask) {
- StringBuffer sbf;
- String str;
- int inetmask = 0, count = 0;
- String[] ipList = mask.split("\\.");
- for (int n = 0; n < ipList.length; n++) {
- sbf = toBin(Integer.parseInt(ipList[n]));
- str = sbf.reverse().toString();
- count = 0;
- for (int i = 0; i < str.length(); i++) {
- i = str.indexOf('1', i);
- if (i == -1) {
- break;
- }
- count++;
- }
- inetmask += count;
- }
- return inetmask;
- }
+ /**
+ * 根据掩码位获取掩码
+ *
+ * @param maskBit 掩码位
+ * @return 掩码
+ */
+ public static String getMaskByMaskBit(int maskBit) {
+ return MaskBit.get(maskBit);
+ }
- /**
- * 计算子网大小
- *
- * @param maskBit 掩码位
- * @param isAll true:全量地址,false:可用地址
- * @return 地址总数
- */
- public static int countByMaskBit(int maskBit, boolean isAll) {
- //如果是可用地址的情况,掩码位小于等于0或大于等于32,则可用地址为0
- boolean isZero = !isAll && (maskBit <= 0 || maskBit >= 32);
- if (isZero) {
- return 0;
- }
- if (isAll) {
- return (int) Math.pow(2, 32 - maskBit);
- } else {
- return (int) Math.pow(2, 32 - maskBit) - 2;
- }
- }
+ /**
+ * 根据开始IP与结束IP计算掩码
+ *
+ * @param fromIp 开始IP
+ * @param toIp 结束IP
+ * @return 掩码x.x.x.x
+ */
+ public static String getMaskByIpRange(String fromIp, String toIp) {
+ long toIpLong = ipv4ToLong(toIp);
+ long fromIpLong = ipv4ToLong(fromIp);
+ if (fromIpLong > toIpLong) {
+ throw new IllegalArgumentException("to IP must be greater than from IP!");
+ }
+ String[] fromIpSplit = StrUtil.splitToArray(fromIp, '.');
+ String[] toIpSplit = StrUtil.splitToArray(toIp, '.');
+ StringBuilder mask = new StringBuilder();
+ for (int i = 0; i < toIpSplit.length; i++) {
+ mask.append(255 - Integer.parseInt(toIpSplit[i]) + Integer.parseInt(fromIpSplit[i])).append(".");
+ }
+ return mask.substring(0, mask.length() - 1);
+ }
- private static StringBuffer toBin(int x) {
- StringBuffer result = new StringBuffer();
- result.append(x % 2);
- x /= 2;
- while (x > 0) {
- result.append(x % 2);
- x /= 2;
- }
- return result;
- }
+ /**
+ * 计算IP区间有多少个IP
+ *
+ * @param fromIp 开始IP
+ * @param toIp 结束IP
+ * @return IP数量
+ */
+ public static int countByIpRange(String fromIp, String toIp) {
+ long toIpLong = ipv4ToLong(toIp);
+ long fromIpLong = ipv4ToLong(fromIp);
+ if (fromIpLong > toIpLong) {
+ throw new IllegalArgumentException("to IP must be greater than from IP!");
+ }
+ int count = 1;
+ int[] fromIpSplit = StrUtil.split(fromIp, '.').stream().mapToInt(Integer::parseInt).toArray();
+ int[] toIpSplit = StrUtil.split(toIp, '.').stream().mapToInt(Integer::parseInt).toArray();
+ for (int i = fromIpSplit.length - 1; i >= 0; i--) {
+ count += (toIpSplit[i] - fromIpSplit[i]) * Math.pow(256, fromIpSplit.length - i - 1);
+ }
+ return count;
+ }
- /**
- * 存储着所有的掩码位及对应的掩码 key:掩码位 value:掩码(x.x.x.x)
- *
- * @return
- */
- private static Map maskBitMap() {
- Map maskBit = new HashMap<>(32);
- maskBit.put("1", "128.0.0.0");
- maskBit.put("2", "192.0.0.0");
- maskBit.put("3", "224.0.0.0");
- maskBit.put("4", "240.0.0.0");
- maskBit.put("5", "248.0.0.0");
- maskBit.put("6", "252.0.0.0");
- maskBit.put("7", "254.0.0.0");
- maskBit.put("8", "255.0.0.0");
- maskBit.put("9", "255.128.0.0");
- maskBit.put("10", "255.192.0.0");
- maskBit.put("11", "255.224.0.0");
- maskBit.put("12", "255.240.0.0");
- maskBit.put("13", "255.248.0.0");
- maskBit.put("14", "255.252.0.0");
- maskBit.put("15", "255.254.0.0");
- maskBit.put("16", "255.255.0.0");
- maskBit.put("17", "255.255.128.0");
- maskBit.put("18", "255.255.192.0");
- maskBit.put("19", "255.255.224.0");
- maskBit.put("20", "255.255.240.0");
- maskBit.put("21", "255.255.248.0");
- maskBit.put("22", "255.255.252.0");
- maskBit.put("23", "255.255.254.0");
- maskBit.put("24", "255.255.255.0");
- maskBit.put("25", "255.255.255.128");
- maskBit.put("26", "255.255.255.192");
- maskBit.put("27", "255.255.255.224");
- maskBit.put("28", "255.255.255.240");
- maskBit.put("29", "255.255.255.248");
- maskBit.put("30", "255.255.255.252");
- maskBit.put("31", "255.255.255.254");
- maskBit.put("32", "255.255.255.255");
- return maskBit;
- }
+ //-------------------------------------------------------------------------------- Private method start
- /**
- * 根据掩码位获取掩码
- *
- * @param maskBit
- * @return
- */
- public static String getMaskByMaskBit(int maskBit) {
- switch (maskBit) {
- case 1:
- return "128.0.0.0";
- case 2:
- return "192.0.0.0";
- case 3:
- return "224.0.0.0";
- case 4:
- return "240.0.0.0";
- case 5:
- return "248.0.0.0";
- case 6:
- return "252.0.0.0";
- case 7:
- return "254.0.0.0";
- case 8:
- return "255.0.0.0";
- case 9:
- return "255.128.0.0";
- case 10:
- return "255.192.0.0";
- case 11:
- return "255.224.0.0";
- case 12:
- return "255.240.0.0";
- case 13:
- return "255.248.0.0";
- case 14:
- return "255.252.0.0";
- case 15:
- return "255.254.0.0";
- case 16:
- return "255.255.0.0";
- case 17:
- return "255.255.128.0";
- case 18:
- return "255.255.192.0";
- case 19:
- return "255.255.224.0";
- case 20:
- return "255.255.240.0";
- case 21:
- return "255.255.248.0";
- case 22:
- return "255.255.252.0";
- case 23:
- return "255.255.254.0";
- case 24:
- return "255.255.255.0";
- case 25:
- return "255.255.255.128";
- case 26:
- return "255.255.255.192";
- case 27:
- return "255.255.255.224";
- case 28:
- return "255.255.255.240";
- case 29:
- return "255.255.255.248";
- case 30:
- return "255.255.255.252";
- case 31:
- return "255.255.255.254";
- case 32:
- return "255.255.255.255";
- default:
- return "";
- }
- }
+ /**
+ * 根据 ip/掩码位 计算IP段的终止IP(Long型)
+ * 注:此接口返回负数,请使用转成字符串后再转Long型
+ *
+ * @param ip 给定的IP,如218.240.38.69
+ * @param maskBit 给定的掩码位,如30
+ * @return 终止IP的长整型表示
+ */
+ private static Long getEndIpLong(String ip, int maskBit) {
+ return getBeginIpLong(ip, maskBit)
+ + ~ipv4ToLong(getMaskByMaskBit(maskBit));
+ }
- /**
- * 根据开始IP与结束IP计算掩码
- *
- * @param fromIp 开始IP
- * @param toIp 结束IP
- * @return 掩码x.x.x.x
- * @throws Exception
- */
- public static String getMaskByIpRange(String fromIp, String toIp) throws Exception {
- Long toIpLong = strIpToLong(toIp);
- Long fromIpLong = strIpToLong(fromIp);
- if (fromIpLong > toIpLong) {
- throw new Exception("开始IP大与结束IP");
- }
- String[] fromIpSplit = fromIp.split("\\.");
- String[] toIpSplit = toIp.split("\\.");
- StringBuilder mask = new StringBuilder();
- for (int i = 0; i < toIpSplit.length; i++) {
- mask.append(255 - Integer.parseInt(toIpSplit[i]) + Integer.parseInt(fromIpSplit[i])).append(".");
- }
- return mask.substring(0, mask.length() - 1);
- }
-
- /**
- * 计算IP区间有多少个IP
- *
- * @param fromIp 开始IP
- * @param toIp 结束IP
- * @return IP数量
- * @throws Exception
- */
- public static int countByIpRange(String fromIp, String toIp) throws Exception {
- Long toIpLong = strIpToLong(toIp);
- Long fromIpLong = strIpToLong(fromIp);
- if (fromIpLong > toIpLong) {
- throw new Exception("开始IP大与结束IP");
- }
- int count = 1;
- int[] fromIpSplit = Arrays.stream(fromIp.split("\\.")).mapToInt(Integer::parseInt).toArray();
- int[] toIpSplit = Arrays.stream(toIp.split("\\.")).mapToInt(Integer::parseInt).toArray();
- for (int i = fromIpSplit.length - 1; i >= 0; i--) {
- count += (toIpSplit[i] - fromIpSplit[i]) * Math.pow(256, fromIpSplit.length - i - 1);
- }
- return count;
- }
+ private static StringBuffer toBin(int x) {
+ StringBuffer result = new StringBuffer();
+ result.append(x % 2);
+ x /= 2;
+ while (x > 0) {
+ result.append(x % 2);
+ x /= 2;
+ }
+ return result;
+ }
+ //-------------------------------------------------------------------------------- Private method end
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java
new file mode 100644
index 000000000..108ee1635
--- /dev/null
+++ b/hutool-core/src/main/java/cn/hutool/core/net/MaskBit.java
@@ -0,0 +1,60 @@
+package cn.hutool.core.net;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 掩码位和掩码之间的Map对应
+ *
+ * @since 5.4.1
+ * @author looly
+ */
+public class MaskBit {
+
+ private static final Map maskBitMap;
+ static {
+ maskBitMap = new HashMap<>(32);
+ maskBitMap.put(1, "128.0.0.0");
+ maskBitMap.put(2, "192.0.0.0");
+ maskBitMap.put(3, "224.0.0.0");
+ maskBitMap.put(4, "240.0.0.0");
+ maskBitMap.put(5, "248.0.0.0");
+ maskBitMap.put(6, "252.0.0.0");
+ maskBitMap.put(7, "254.0.0.0");
+ maskBitMap.put(8, "255.0.0.0");
+ maskBitMap.put(9, "255.128.0.0");
+ maskBitMap.put(10, "255.192.0.0");
+ maskBitMap.put(11, "255.224.0.0");
+ maskBitMap.put(12, "255.240.0.0");
+ maskBitMap.put(13, "255.248.0.0");
+ maskBitMap.put(14, "255.252.0.0");
+ maskBitMap.put(15, "255.254.0.0");
+ maskBitMap.put(16, "255.255.0.0");
+ maskBitMap.put(17, "255.255.128.0");
+ maskBitMap.put(18, "255.255.192.0");
+ maskBitMap.put(19, "255.255.224.0");
+ maskBitMap.put(20, "255.255.240.0");
+ maskBitMap.put(21, "255.255.248.0");
+ maskBitMap.put(22, "255.255.252.0");
+ maskBitMap.put(23, "255.255.254.0");
+ maskBitMap.put(24, "255.255.255.0");
+ maskBitMap.put(25, "255.255.255.128");
+ maskBitMap.put(26, "255.255.255.192");
+ maskBitMap.put(27, "255.255.255.224");
+ maskBitMap.put(28, "255.255.255.240");
+ maskBitMap.put(29, "255.255.255.248");
+ maskBitMap.put(30, "255.255.255.252");
+ maskBitMap.put(31, "255.255.255.254");
+ maskBitMap.put(32, "255.255.255.255");
+ }
+
+ /**
+ * 根据掩码位获取掩码
+ *
+ * @param maskBit 掩码位
+ * @return 掩码
+ */
+ public static String get(int maskBit) {
+ return maskBitMap.get(maskBit);
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
index 1c218677f..8f239c751 100644
--- a/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/net/NetUtil.java
@@ -5,7 +5,6 @@ import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Filter;
-import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
@@ -58,19 +57,10 @@ public class NetUtil {
*
* @param longIP IP的long表示形式
* @return IP V4 地址
+ * @see Ipv4Util#longToIpv4(long)
*/
public static String longToIpv4(long longIP) {
- final StringBuilder sb = StrUtil.builder();
- // 直接右移24位
- sb.append((longIP >>> 24));
- sb.append(".");
- // 将高8位置0,然后右移16位
- sb.append(((longIP & 0x00FFFFFF) >>> 16));
- sb.append(".");
- sb.append(((longIP & 0x0000FFFF) >>> 8));
- sb.append(".");
- sb.append((longIP & 0x000000FF));
- return sb.toString();
+ return Ipv4Util.longToIpv4(longIP);
}
/**
@@ -78,22 +68,10 @@ public class NetUtil {
*
* @param strIP IP V4 地址
* @return long值
+ * @see Ipv4Util#ipv4ToLong(String)
*/
public static long ipv4ToLong(String strIP) {
- if (Validator.isIpv4(strIP)) {
- long[] ip = new long[4];
- // 先找到IP地址字符串中.的位置
- int position1 = strIP.indexOf(".");
- int position2 = strIP.indexOf(".", position1 + 1);
- int position3 = strIP.indexOf(".", position2 + 1);
- // 将每个.之间的字符串转换成整型
- ip[0] = Long.parseLong(strIP.substring(0, position1));
- ip[1] = Long.parseLong(strIP.substring(position1 + 1, position2));
- ip[2] = Long.parseLong(strIP.substring(position2 + 1, position3));
- ip[3] = Long.parseLong(strIP.substring(position3 + 1));
- return (ip[0] << 24) + (ip[1] << 16) + (ip[2] << 8) + ip[3];
- }
- return 0;
+ return Ipv4Util.ipv4ToLong(strIP);
}
/**
diff --git a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java
index 836897cba..ab8ba9ef1 100644
--- a/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/thread/ThreadUtil.java
@@ -92,10 +92,11 @@ public class ThreadUtil {
* 获得一个新的线程池,并指定最大任务队列大小
* 如果maximumPoolSize >= corePoolSize,在没有新任务加入的情况下,多出的线程将最多保留60s
*
- * @param corePoolSize 初始线程池大小
- * @param maximumPoolSize 最大线程池大小
+ * @param corePoolSize 初始线程池大小
+ * @param maximumPoolSize 最大线程池大小
* @param maximumQueueSize 最大任务队列大小
* @return {@link ThreadPoolExecutor}
+ * @since 5.4.1
*/
public static ExecutorService newExecutor(int corePoolSize, int maximumPoolSize, int maximumQueueSize) {
return ExecutorBuilder.create()