mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
1.update code;
2.fix doc; 3.add test method;
This commit is contained in:
parent
09c3dd9565
commit
f79c670446
@ -8,13 +8,12 @@ import cn.hutool.core.util.CharUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
|
||||
/**
|
||||
* IPV4地址工具类
|
||||
*
|
||||
* <p>pr自:https://gitee.com/loolly/hutool/pulls/161</p>
|
||||
* <p><a href="https://gitee.com/loolly/hutool/pulls/161">工具类来源pr</a></p>
|
||||
*
|
||||
* <p>名词解释:
|
||||
* <ul>
|
||||
@ -22,7 +21,7 @@ import java.util.regex.Matcher;
|
||||
* <li>ip的Long类型:有效位32位,每8位可以转为一个十进制数,例如:0xC0A802FA, 转为点分十进制是:192.168.2.250</li>
|
||||
* <li>掩码地址:点分十进制,例如:255.255.255.0</li>
|
||||
* <li>掩码位:int类型,例如 24, 它代表的掩码地址为:255.255.255.0;掩码位和掩码地址的相互转换,请使用 {@link MaskBit}</li>
|
||||
* <li>CIDR:无类域间路由,形如:xxx.xxx.xxx.xxx/掩码位</li>
|
||||
* <li>CIDR:无类域间路由,形如:xxx.xxx.xxx.xxx/掩码位,192.168.1.101/24</li>
|
||||
* <li>全量地址:区间内所有ip地址,包含区间两端</li>
|
||||
* <li>可用地址:区间内所有ip地址,但是不包含区间两端</li>
|
||||
* </ul>
|
||||
@ -39,7 +38,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
*
|
||||
* @param ip IP地址,点分十进制,如:xxx.xxx.xxx.xxx
|
||||
* @param mask 掩码地址,点分十进制,如:255.255.255.0
|
||||
* @return 返回 {@literal xxx.xxx.xxx.xxx/掩码位} 的格式
|
||||
* @return 返回 {@literal xxx.xxx.xxx.xxx/掩码位} 的格式,例如:192.168.1.101/24
|
||||
*/
|
||||
public static String formatIpBlock(final String ip, final String mask) {
|
||||
return ip + IP_MASK_SPLIT_MARK + getMaskBitByMask(mask);
|
||||
@ -78,35 +77,24 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
assertMaskBitValid(maskBit);
|
||||
// 避免后续的计算异常
|
||||
if (countByMaskBit(maskBit, isAll) == 0) {
|
||||
return new ArrayList<>(0);
|
||||
return ListUtil.zero();
|
||||
}
|
||||
|
||||
if (maskBit == IPV4_MASK_BIT_MAX) {
|
||||
final List<String> list = new ArrayList<>(isAll ? 1 : 0);
|
||||
if (isAll) {
|
||||
list.add(ip);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
String startIp = getBeginIpStr(ip, maskBit);
|
||||
String endIp = getEndIpStr(ip, maskBit);
|
||||
final long startIp = getBeginIpLong(ip, maskBit);
|
||||
final long endIp = getEndIpLong(ip, maskBit);
|
||||
if (isAll) {
|
||||
return list(startIp, endIp);
|
||||
}
|
||||
|
||||
// 可用地址,排除开始和结束的地址
|
||||
int lastDotIndex = startIp.lastIndexOf(CharUtil.DOT) + 1;
|
||||
startIp = StrUtil.subPre(startIp, lastDotIndex) +
|
||||
(Integer.parseInt(Objects.requireNonNull(StrUtil.subSuf(startIp, lastDotIndex))) + 1);
|
||||
lastDotIndex = endIp.lastIndexOf(CharUtil.DOT) + 1;
|
||||
endIp = StrUtil.subPre(endIp, lastDotIndex) +
|
||||
(Integer.parseInt(Objects.requireNonNull(StrUtil.subSuf(endIp, lastDotIndex))) - 1);
|
||||
return list(startIp, endIp);
|
||||
// 可用地址: 排除开始和结束的地址
|
||||
if (startIp + 1 > endIp - 1) {
|
||||
return ListUtil.zero();
|
||||
}
|
||||
return list(startIp + 1, endIp - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得 指定区间内 所有ip地址
|
||||
* 获得 指定区间内 所有ip地址
|
||||
*
|
||||
* @param ipFrom 开始IP,包含,点分十进制
|
||||
* @param ipTo 结束IP,包含,点分十进制
|
||||
@ -128,41 +116,14 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
final int count = countByIpRange(ipFrom, ipTo);
|
||||
|
||||
final List<String> ips = new ArrayList<>(count);
|
||||
// 是否是循环的第一个值
|
||||
boolean aIsStart = true, bIsStart = true, cIsStart = true;
|
||||
// 是否是循环的最后一个值
|
||||
boolean aIsEnd, bIsEnd, cIsEnd;
|
||||
// 循环的结束值
|
||||
final int aEnd = getPartOfIpLong(ipTo, 1);
|
||||
int bEnd;
|
||||
int cEnd;
|
||||
int dEnd;
|
||||
final StringBuilder sb = StrUtil.builder(15);
|
||||
for (int a = getPartOfIpLong(ipFrom, 1); a <= aEnd; a++) {
|
||||
aIsEnd = (a == aEnd);
|
||||
// 本次循环的结束结束值
|
||||
bEnd = aIsEnd ? getPartOfIpLong(ipTo, 2) : 255;
|
||||
for (int b = (aIsStart ? getPartOfIpLong(ipFrom, 2) : 0); b <= bEnd; b++) {
|
||||
// 在上一个循环是最后值的基础上进行判断
|
||||
bIsEnd = aIsEnd && (b == bEnd);
|
||||
cEnd = bIsEnd ? getPartOfIpLong(ipTo, 3) : 255;
|
||||
for (int c = (bIsStart ? getPartOfIpLong(ipFrom, 3) : 0); c <= cEnd; c++) {
|
||||
// 在之前循环是最后值的基础上进行判断
|
||||
cIsEnd = bIsEnd && (c == cEnd);
|
||||
dEnd = cIsEnd ? getPartOfIpLong(ipTo, 4) : 255;
|
||||
for (int d = (cIsStart ? getPartOfIpLong(ipFrom, 4) : 0); d <= dEnd; d++) {
|
||||
sb.setLength(0);
|
||||
ips.add(sb.append(a).append(CharUtil.DOT)
|
||||
.append(b).append(CharUtil.DOT)
|
||||
.append(c).append(CharUtil.DOT)
|
||||
.append(d)
|
||||
.toString());
|
||||
}
|
||||
cIsStart = false;
|
||||
}
|
||||
bIsStart = false;
|
||||
}
|
||||
aIsStart = false;
|
||||
for (long ip = ipFrom, end = ipTo + 1; ip < end; ip++) {
|
||||
sb.setLength(0);
|
||||
ips.add(sb.append((int) (ip >> 24) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) (ip >> 16) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) (ip >> 8) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) ip & 0xFF)
|
||||
.toString());
|
||||
}
|
||||
return ips;
|
||||
}
|
||||
@ -170,15 +131,15 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
/**
|
||||
* 根据 ip的long值 获取 ip字符串,即:xxx.xxx.xxx.xxx
|
||||
*
|
||||
* @param longIp IP的long表示形式
|
||||
* @param ip IP的long表示形式
|
||||
* @return 点分十进制ip地址
|
||||
*/
|
||||
public static String longToIpv4(final long longIp) {
|
||||
public static String longToIpv4(final long ip) {
|
||||
return StrUtil.builder(15)
|
||||
.append(getPartOfIpLong(longIp, 1)).append(CharUtil.DOT)
|
||||
.append(getPartOfIpLong(longIp, 2)).append(CharUtil.DOT)
|
||||
.append(getPartOfIpLong(longIp, 3)).append(CharUtil.DOT)
|
||||
.append(getPartOfIpLong(longIp, 4))
|
||||
.append((int) (ip >> 24) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) (ip >> 16) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) (ip >> 8) & 0xFF).append(CharUtil.DOT)
|
||||
.append((int) ip & 0xFF)
|
||||
.toString();
|
||||
}
|
||||
|
||||
@ -214,7 +175,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
* @param maskBit 给定的掩码位,如:30
|
||||
* @return 起始IP的长整型表示
|
||||
*/
|
||||
public static Long getBeginIpLong(final String ip, final int maskBit) {
|
||||
public static long getBeginIpLong(final String ip, final int maskBit) {
|
||||
assertMaskBitValid(maskBit);
|
||||
return ipv4ToLong(ip) & MaskBit.getMaskIpLong(maskBit);
|
||||
}
|
||||
@ -237,8 +198,8 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
* @param maskBit 给定的掩码位,如:30
|
||||
* @return 终止IP的长整型表示
|
||||
*/
|
||||
public static Long getEndIpLong(final String ip, final int maskBit) {
|
||||
return getBeginIpLong(ip, maskBit) + ~MaskBit.getMaskIpLong(maskBit);
|
||||
public static long getEndIpLong(final String ip, final int maskBit) {
|
||||
return getBeginIpLong(ip, maskBit) + (IPV4_NUM_MAX & ~MaskBit.getMaskIpLong(maskBit));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -257,7 +218,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
/**
|
||||
* 获取 子网内的 地址总数
|
||||
*
|
||||
* @param maskBit 掩码位,取值范围:({@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}]
|
||||
* @param maskBit 掩码位,取值范围:({@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}]
|
||||
* @param isAll true:全量地址,false:可用地址
|
||||
* @return 子网内地址总数
|
||||
*/
|
||||
@ -276,10 +237,11 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
/**
|
||||
* 根据 掩码位 获取 掩码地址
|
||||
*
|
||||
* @param maskBit 掩码位,如:24,取值范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}]
|
||||
* @param maskBit 掩码位,如:24,取值范围:[{@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}]
|
||||
* @return 掩码地址,点分十进制,如:255.255.255.0
|
||||
*/
|
||||
public static String getMaskByMaskBit(final int maskBit) {
|
||||
assertMaskBitValid(maskBit);
|
||||
return MaskBit.get(maskBit);
|
||||
}
|
||||
|
||||
@ -296,10 +258,10 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
Assert.isTrue(fromIpLong <= toIpLong, "Start IP must be less than or equal to end IP!");
|
||||
|
||||
return StrUtil.builder(15)
|
||||
.append(255 - getPartOfIpLong(toIpLong, 1) + getPartOfIpLong(fromIpLong, 1)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIpLong(toIpLong, 2) + getPartOfIpLong(fromIpLong, 2)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIpLong(toIpLong, 3) + getPartOfIpLong(fromIpLong, 3)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIpLong(toIpLong, 4) + getPartOfIpLong(fromIpLong, 4))
|
||||
.append(255 - getPartOfIp(toIpLong, 1) + getPartOfIp(fromIpLong, 1)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIp(toIpLong, 2) + getPartOfIp(fromIpLong, 2)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIp(toIpLong, 3) + getPartOfIp(fromIpLong, 3)).append(CharUtil.DOT)
|
||||
.append(255 - getPartOfIp(toIpLong, 4) + getPartOfIp(fromIpLong, 4))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@ -311,9 +273,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
* @return IP数量
|
||||
*/
|
||||
public static int countByIpRange(final String fromIp, final String toIp) {
|
||||
final long toIpLong = ipv4ToLong(toIp);
|
||||
final long fromIpLong = ipv4ToLong(fromIp);
|
||||
return countByIpRange(fromIpLong, toIpLong);
|
||||
return countByIpRange(ipv4ToLong(fromIp), ipv4ToLong(toIp));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,10 +287,10 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
Assert.isTrue(fromIp <= toIp, "Start IP must be less than or equal to end IP!");
|
||||
|
||||
int count = 1;
|
||||
count += (getPartOfIpLong(toIp, 4) - getPartOfIpLong(fromIp, 4));
|
||||
count += (getPartOfIpLong(toIp, 3) - getPartOfIpLong(fromIp, 3)) << 8;
|
||||
count += (getPartOfIpLong(toIp, 2) - getPartOfIpLong(fromIp, 2)) << 16;
|
||||
count += (getPartOfIpLong(toIp, 1) - getPartOfIpLong(fromIp, 1)) << 24;
|
||||
count += (getPartOfIp(toIp, 4) - getPartOfIp(fromIp, 4))
|
||||
+ ((getPartOfIp(toIp, 3) - getPartOfIp(fromIp, 3)) << 8)
|
||||
+ ((getPartOfIp(toIp, 2) - getPartOfIp(fromIp, 2)) << 16)
|
||||
+ ((getPartOfIp(toIp, 1) - getPartOfIp(fromIp, 1)) << 24);
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -347,7 +307,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
/**
|
||||
* 判断掩码位是否合法
|
||||
*
|
||||
* @param maskBit 掩码位,有效范围:[{@link Ipv4Pool#IPV4_MASK_BIT_VALID_MIN}, {@link Ipv4Pool#IPV4_MASK_BIT_MAX}]
|
||||
* @param maskBit 掩码位,有效范围:[{@link #IPV4_MASK_BIT_VALID_MIN}, {@link #IPV4_MASK_BIT_MAX}]
|
||||
* @return true:掩码位合法;false:掩码位不合法
|
||||
*/
|
||||
public static boolean isMaskBitValid(final int maskBit) {
|
||||
@ -424,7 +384,7 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
|
||||
/**
|
||||
* 获取ip(Long类型)指定部分的十进制值,即,{@literal X.X.X.X }形式中每个部分的值
|
||||
* <p>例如,ip为{@literal 0xC0A802FA},第1部分的值为:
|
||||
* <p>例如,ip为{@literal 0xC0A802FA}:
|
||||
* <ul>
|
||||
* <li>第1部分的值为:{@literal 0xC0},十进制值为:192</li>
|
||||
* <li>第2部分的值为:{@literal 0xA8},十进制值为:168</li>
|
||||
@ -437,16 +397,16 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
* @return ip地址指定部分的十进制值
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public static int getPartOfIpLong(final long ip, final int position) {
|
||||
public static int getPartOfIp(final long ip, final int position) {
|
||||
switch (position) {
|
||||
case 1:
|
||||
return ((int) ip >> 24) & 0xFF;
|
||||
return (int) (ip >> 24) & 0xFF;
|
||||
case 2:
|
||||
return ((int) ip >> 16) & 0xFF;
|
||||
return (int) (ip >> 16) & 0xFF;
|
||||
case 3:
|
||||
return ((int) ip >> 8) & 0xFF;
|
||||
return (int) (ip >> 8) & 0xFF;
|
||||
case 4:
|
||||
return ((int) ip) & 0xFF;
|
||||
return (int)ip & 0xFF;
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal position of ip Long: " + position);
|
||||
}
|
||||
@ -462,10 +422,14 @@ public class Ipv4Util implements Ipv4Pool {
|
||||
private static long matchAddress(final Matcher matcher) {
|
||||
int addr = 0;
|
||||
// 每个点分十进制数字 转为 8位二进制
|
||||
for (int i = 1; i <= 4; ++i) {
|
||||
addr <<= 8;
|
||||
addr |= Integer.parseInt(matcher.group(i));
|
||||
}
|
||||
addr |= Integer.parseInt(matcher.group(1));
|
||||
addr <<= 8;
|
||||
addr |= Integer.parseInt(matcher.group(2));
|
||||
addr <<= 8;
|
||||
addr |= Integer.parseInt(matcher.group(3));
|
||||
addr <<= 8;
|
||||
addr |= Integer.parseInt(matcher.group(4));
|
||||
|
||||
// int的最高位无法直接使用,转为Long
|
||||
if (addr < 0) {
|
||||
return IPV4_NUM_MAX & addr;
|
||||
|
@ -5,6 +5,9 @@ import cn.hutool.core.map.BiMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import static cn.hutool.core.net.Ipv4Pool.IPV4_MASK_BIT_MAX;
|
||||
import static cn.hutool.core.net.Ipv4Pool.IPV4_NUM_MAX;
|
||||
|
||||
/**
|
||||
* 掩码位和掩码之间的Map对应
|
||||
*
|
||||
@ -84,6 +87,6 @@ public class MaskBit {
|
||||
*/
|
||||
public static long getMaskIpLong(final int maskBit) {
|
||||
Assert.isTrue(MASK_BIT_MAP.containsKey(maskBit), "非法的掩码位数:{}", maskBit);
|
||||
return (0xffffffffL << (32 - maskBit)) & 0xffffffffL;
|
||||
return (IPV4_NUM_MAX << (IPV4_MASK_BIT_MAX - maskBit)) & IPV4_NUM_MAX;
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,14 @@ import org.junit.function.ThrowingRunnable;
|
||||
public class Ipv4UtilTest {
|
||||
|
||||
@Test
|
||||
public void getMaskBitByMaskTest(){
|
||||
public void formatIpBlockTest() {
|
||||
for (int i = Ipv4Util.IPV4_MASK_BIT_VALID_MIN; i < Ipv4Util.IPV4_MASK_BIT_MAX; i++) {
|
||||
Assert.assertEquals("192.168.1.101/" + i, Ipv4Util.formatIpBlock("192.168.1.101", Ipv4Util.getMaskByMaskBit(i)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaskBitByMaskTest() {
|
||||
final int maskBitByMask = Ipv4Util.getMaskBitByMask("255.255.255.0");
|
||||
Assert.assertEquals(24, maskBitByMask);
|
||||
}
|
||||
@ -19,7 +26,7 @@ public class Ipv4UtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaskByMaskBitTest(){
|
||||
public void getMaskByMaskBitTest() {
|
||||
final String mask = Ipv4Util.getMaskByMaskBit(24);
|
||||
Assert.assertEquals("255.255.255.0", mask);
|
||||
}
|
||||
@ -39,7 +46,7 @@ public class Ipv4UtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getEndIpStrTest(){
|
||||
public void getEndIpStrTest() {
|
||||
final String ip = "192.168.1.1";
|
||||
final int maskBitByMask = Ipv4Util.getMaskBitByMask("255.255.255.0");
|
||||
final String endIpStr = Ipv4Util.getEndIpStr(ip, maskBitByMask);
|
||||
@ -47,7 +54,7 @@ public class Ipv4UtilTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listTest(){
|
||||
public void listTest() {
|
||||
final String ip = "192.168.100.2";
|
||||
testGenerateIpList(ip, 22, false);
|
||||
testGenerateIpList(ip, 22, true);
|
||||
@ -66,7 +73,10 @@ public class Ipv4UtilTest {
|
||||
|
||||
testGenerateIpList(ip, 32, false);
|
||||
testGenerateIpList(ip, 32, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void listTest2() {
|
||||
testGenerateIpList("10.1.0.1", "10.2.1.2");
|
||||
|
||||
testGenerateIpList("10.2.1.1", "10.2.1.2");
|
||||
@ -182,4 +192,13 @@ public class Ipv4UtilTest {
|
||||
Assert.assertFalse(Ipv4Util.isPublicIP("172.20.10.1"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMaskBitByIpRange() {
|
||||
final String ip = "192.168.100.2";
|
||||
for (int i = 1; i <= 32; i++) {
|
||||
String beginIpStr = Ipv4Util.getBeginIpStr(ip, i);
|
||||
String endIpStr = Ipv4Util.getEndIpStr(ip, i);
|
||||
Assert.assertEquals(Ipv4Util.getMaskByMaskBit(i), Ipv4Util.getMaskByIpRange(beginIpStr, endIpStr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -348,8 +348,9 @@ public class Entity extends Dict {
|
||||
* 获得字符串值<br>
|
||||
* 支持Clob、Blob、RowId
|
||||
*
|
||||
* @param field 字段名
|
||||
* @param charset 编码
|
||||
* @param field 字段名
|
||||
* @param charset 编码
|
||||
* @param defaultValue 默认值
|
||||
* @return 字段对应值
|
||||
*/
|
||||
public String getStr(final String field, final Charset charset, final String defaultValue) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user