在Java中验证IPv4字符串

Mat*_* B. 45 java string ip validation

Bellow方法验证字符串是否正确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;
    }
}
Run Code Online (Sandbox Code Playgroud)

rou*_*ble 53

这是一个更容易阅读,效率稍低的方式,你可以去做.

public static boolean validIP (String ip) {
    try {
        if ( ip == null || ip.isEmpty() ) {
            return false;
        }

        String[] parts = ip.split( "\\." );
        if ( parts.length != 4 ) {
            return false;
        }

        for ( String s : parts ) {
            int i = Integer.parseInt( s );
            if ( (i < 0) || (i > 255) ) {
                return false;
            }
        }
        if ( ip.endsWith(".") ) {
            return false;
        }

        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 我更喜欢这种方法. (4认同)
  • @rouble 我不知道。但是,我使用的所有网络堆栈都接受像 192.168.1 (192.168.0.1) 和 10.1 (10.0.0.1) 这样的地址。 (2认同)

coo*_*ird 46

更新: Commons-HttpClient及其后继者HttpComponents-HttpClient已采用此功能.你可以像这样使用它的这个版本:InetAddressUtils.isIPv4Address(Str).


Apache Commons Validator的开发版本有一个InetAddressValidator类,它有一个isValidInet4Address(String)方法来执行检查以查看给定的String是有效的IPv4地址.

源代码可以从储备库中查看,这样有可能改进提供一些思路,如果你觉得有什么.

快速浏览一下提供的代码,可以看出你的方法是Pattern在每次调用方法时编译一个.我会将Pattern该类移到一个static字段,以避免每次调用时昂贵的模式编译过程.


Ste*_*n L 21

如果要使用具有支持IPv4和IPv6支持的已发布版本的库,则可以使用Guava

boolean isValid = InetAddresses.isInetAddress("1.2.3.4");
Run Code Online (Sandbox Code Playgroud)


Ran*_*niz 16

这是一个使用Java 8流来检查地址是否包含0到255之间的4个数字的解决方案,用点分隔:

public class IpValidation {

    /**
     * Check that a string represents a decimal number
     * @param string The string to check
     * @return true if string consists of only numbers without leading zeroes, false otherwise
     */
    public static boolean isDecimal(String string) {
        // Check whether string has a leading zero but is not "0"
        if (string.startsWith("0")) {
            return string.length() == 1;
        }
        for(char c : string.toCharArray()) {
            if(c < '0' || c > '9') {
                return false;
            }
        }
        return true;
    }

    public static boolean isIp(String string) {
        String[] parts = string.split("\\.", -1);
        return parts.length == 4 // 4 parts
                && Arrays.stream(parts)
                .filter(IpValidation::isDecimal) // Only decimal numbers
                .map(Integer::parseInt)
                .filter(i -> i <= 255 && i >= 0) // Must be inside [0, 255]
                .count() == 4; // 4 numerical parts inside [0, 255]
    }
}
Run Code Online (Sandbox Code Playgroud)

  • `ping 192.168.1.09` ping:无法解析192.168.1.09:未知主机摘要:以0开头的IP段表示该段是八进制的,因此我们还需要验证剩余的数字不包含7,8(我承认我以前不知道这个:那个yi给出的例子是172.013.1.2正确的测试案例是172.13.1.008 - 哪个失败了)长话短说:上面的验证不正确,可能导致误报 (4认同)
  • “在一种情况下有效,这对我来说已经足够了。” 这是反对票的充足理由。遗憾的是,这个答案得到了赏金。一种情况有效的原因是以“0”(在本例中为“001”)开头的数字在八进制和十进制中的含义相同。只有当只有一个非零数字,后面没有零,并且该数字不是 8 或 9 时,这才是正确的。哎呀。 (2认同)

Mic*_*zka 14

如果你不介意在无效的ip-address上使用dns解析www.example.com,你可以使用InetAddress方法来检查:

public static final boolean checkIPv4(final String ip) {
    boolean isIPv4;
    try {
    final InetAddress inet = InetAddress.getByName(ip);
    isIPv4 = inet.getHostAddress().equals(ip)
            && inet instanceof Inet4Address;
    } catch (final UnknownHostException e) {
    isIPv4 = false;
    }
    return isIPv4;
}
Run Code Online (Sandbox Code Playgroud)

该方法检查它是否是Inet4Address的实例,以及参数是否为ip-address而不是主机名.如果您希望将大量主机名作为参数,请注意此实现使用DNS尝试解析它.这可能是一个性能问题.

否则,您可以 boolean sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String src)了解如何解析String以进行IPv4检查.

  • FWIW,这就是我通常做的事情:首先使用一个简单的正则表达式来检查参数是否包含4个以点分隔的数字(我不会尝试检查数字是否在范围内,等等,只是一般格式).如果第一次检查通过,那么我在此答案中使用InetAddress来完成验证. (2认同)

big*_*awn 7

查找正则表达式例如

package com.mkyong.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class IPAddressValidator{

    private Pattern pattern;
    private Matcher matcher;

    private static final String IPADDRESS_PATTERN = 
        "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
        "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";

    public IPAddressValidator(){
      pattern = Pattern.compile(IPADDRESS_PATTERN);
    }

   /**
    * Validate ip address with regular expression
    * @param ip ip address for validation
    * @return true valid ip address, false invalid ip address
    */
    public boolean validate(final String ip){         
      matcher = pattern.matcher(ip);
      return matcher.matches();             
    }
}
Run Code Online (Sandbox Code Playgroud)


arc*_*rcs 5

我认为这个解决方案非常优雅,但需要花一点时间来理解它.

基本思想是采用子字符串而不是验证它.
请注意,我切换x和y,因为子字符串的开头始终是最后一个加1的结尾.

该解决方案比正则表达式变体快约20倍,比分裂快2倍.

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

    try {
        int x = 0;
        int y = ip.indexOf('.');

        if (y == -1 || ip.charAt(x) == '-' || Integer.parseInt(ip.substring(x, y)) > 255) return false;

        x = ip.indexOf('.', ++y);
        if (x == -1 || ip.charAt(y) == '-' || Integer.parseInt(ip.substring(y, x)) > 255) return false;

        y = ip.indexOf('.', ++x);
        return  !(y == -1 ||
                ip.charAt(x) == '-' ||
                Integer.parseInt(ip.substring(x, y)) > 255 ||
                ip.charAt(++y) == '-' ||
                Integer.parseInt(ip.substring(y, ip.length())) > 255 ||
                ip.charAt(ip.length()-1) == '.');

    } catch (NumberFormatException e) {
        return false;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您知道IP有很多错误,请考虑在第一个if下面添加以下代码.这将使代码慢1.5倍但如果出现错误则将其提高700倍

    for (int i = 0; i < ip.length(); i++) {
        if (!Character.isDigit(ip.charAt(i)) && ip.charAt(i) != '.') return false;
    }
Run Code Online (Sandbox Code Playgroud)


ban*_*e19 5

尝试对 IPv4 使用以下正则表达式

String ip4Regex="^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$";
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你 :)