在Java中验证IPv4字符串

60

下面的方法用于验证字符串是否为正确的IPv4地址,如果是有效的则返回true。如果有更好的正则表达式和优雅的方法,请提出建议:

public static boolean validIP(String ip) {
    if (ip == null || ip.isEmpty()) return false;
    ip = ip.trim();
    if ((ip.length() < 6) & (ip.length() > 15)) return false;

    try {
        Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
        Matcher matcher = pattern.matcher(ip);
        return matcher.matches();
    } catch (PatternSyntaxException ex) {
        return false;
    }
}

有不同的表示方法可用。您正在寻找点十进制表示法:请参阅http://en.wikipedia.org/wiki/IPv4#Address_representations - Michael Konietzka
一个ip.length()为7是有效的,例如0.0.0.0是7个字符,你的方法将返回false。 - rouble
2
我想知道为什么这仍然不是某些第三方库的一部分。我的意思是避免使用第三方库是好的,但是找到适合它的正则表达式非常容易出错,这在我看来比使用第三方API更糟糕。 - Arthur Eirich
1
正则表达式没问题,你只需要将 [0-9] 替换为 \d 并且把模式编译移出方法,这样就不必每次都编译了。 - Javier Diaz
17个回答

3
我认为正确的方法是构建一个IPAddress类,并通过给出IP地址的字符串表示来实例化它。
这样,您可以将不同的验证步骤拆分为实例方法,并获得一些关注点分离
例如,这里通常是自己的方法,只需调用isEmpty即可:
return (ip == null || ip.isEmpty());

此外,这应该是一个独立的方法,你可以将其命名为hasProbableLength
ip = ip.trim();
return ((ip.length() < 6) & (ip.length() > 15));

这里有很多事情要做。我会尝试拆分它,并尝试完全跳过正则表达式。

try {
    Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
    Matcher matcher = pattern.matcher(ip);
    return matcher.matches();
} catch (PatternSyntaxException ex) {
    return false;
}

我会首先按点号将字符串分割成四组,并确保每组都恰好包含一个值。这个方法称为divideIntoGroups
然后,我会验证每个组的值是否在0到255之间。这个方法称为validateGroups
现在,如果您想扩展此类以查找IP地址是本地主机还是广播地址,那么这非常容易做到。这就是关注点分离给您的。
您还可以准确地确定IP地址字符串验证中违反了哪个验证规则。这是正则表达式无法实现的。

如果可能的话,您可以添加Java代码和测试用例,使用main()方法吗? - deepakl.2000

3

IPAddress Java库可以实现此功能。该链接提供了javadoc文件。免责声明:我是项目经理。

该库支持IPv4和IPv6地址的透明验证,因此以下验证两种类型的地址相同,并且还支持CIDR前缀长度IPC4地址。它还支持像inet_aton这样不太常见的格式(例如在另一个答案中提到了10.8)

验证地址是否有效:

    String str = "1.2.3.4";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         ...
    } catch(AddressStringException e) {
        //e.getMessage provides validation issue
    }

2

我发现检查给定IP地址是否正确的最简单方法是使用commons-validator-1.4.0.jar,其中包含以下类:--

org.apache.commons.validator.routines.InetAddressValidator

InetAddressValidator

例如:

InetAddressValidator inetValidator = InetAddressValidator.getInstance();
inetValidator.isValidInet4Address(yourIPAddress);

使用这个简单的正则表达式:--
  "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";

2
该正则表达式虽然可以接受999.999.999.999,但实际上是无用的。 - Raniz

2
这对你很有用,

boolean isIPv4Address(String inputString) {
    String[] splitString = inputString.split("[.]");
    if (splitString.length > 4) {
        return false;
    }
    for (String string : splitString) {
        if (string.isEmpty()) {
            return false;
        }
        if (!string.matches("[0-9]{1,3}")) {
            return false;
        }
        int number = Integer.parseInt(string);
        if (!(number >= 0 && number <= 255)) {
            return false;
        }
    }
    return true;
}


以上的解决方案适用于 IPv4 地址和 IPv6 地址吗?如果可能,您能添加一些测试用例吗? - deepakl.2000

1
我建议使用你正在开发的平台/框架上提供的功能。
如果没有你认为足够好的东西,那么你可能只想将已编译的正则表达式添加到帮助类中。例如,这就是Android框架的做法:here
public static final Pattern IP_ADDRESS
    = Pattern.compile(
        "((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
        + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
        + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
        + "|[1-9][0-9]|[0-9]))");

1
boolean isValid = inetAddressValidator.isValid(hostName) || hostName.equalsIgnoreCase("localhost");

与coobird的答案相同。只需将localhost添加到语句中。大多数环境将“localhost”视为有效的主机名。它不是ipv4格式,但应包含在考虑有效性时。

1
public static boolean ipv4Check(String ipAddress){

    try{
        if(ipAddress!=null && !ipAddress.isEmpty()){
            String [] ip = ipAddress.split("\\.");
            if(ip.length!=4)
                return false;

            for(int i=0;i<=ip.length-1;i++){
                int j=Integer.parseInt(ip[i]);
                if(j<0 || j>255){
                    return false;
                }
            }
            if ( ipAddress.endsWith(".") ) {
                return false;
            }
            if ( ipAddress.startsWith(".") ) {
                return false;
            }

        }
        return true;
    } catch (NumberFormatException ex) {
        return false;
    }       
}

以上解决方案是否适用于IPv4Address和IPv6Address?如果可能的话,您能添加测试用例吗? - deepakl.2000
这是为了检查IPv4而不是IPv6,因为它们具有不同的结构。 - Amit Kumar
你能否也添加IPv6Address的Java解决方案?你能否在Java的public static void main方法中添加IPv4Address和IPv6Address的测试用例?@Amit Kumar - deepakl.2000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接