Validating IPv4 string in Java

2019-01-08 22:24发布

Bellow method is validating if string is correct IPv4 address it returns true if it is valid. Any improvements in regex and elegance would be very appreciated:

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;
    }
}

16条回答
地球回转人心会变
2楼-- · 2019-01-08 22:29

Here is an easier-to-read, slightly less efficient, way you could go about it.

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;
    }
}
查看更多
混吃等死
3楼-- · 2019-01-08 22:29

If you don't mind using dns resolution on invalid ip-addresses like www.example.com, you can use the InetAddress methods to check:

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;
}

The method checks if it is an instance of Inet4Address and if the parameter was the ip-address and not the hostname. If you expect a lot of hostnames as parameters, beware that this implementation uses DNS to try to resolve it. This might be a performance concern.

Otherwise you can have a peak into boolean sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String src) how the String is parsed there for IPv4-check.

查看更多
Anthone
4楼-- · 2019-01-08 22:29

The IPAddress Java library will do it. The javadoc is available at the link. Disclaimer: I am the project manager.

This library supports IPv4 and IPv6 transparently, so validating either works the same below, and it also supports CIDR prefix-length IPC4 addresses as well. It supports the more unusual formats like inet_aton (for example 10.8 was mentioned in another answer here)

Verify if an address is valid:

    String str = "1.2.3.4";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         ...
    } catch(AddressStringException e) {
        //e.getMessage provides validation issue
    }
查看更多
做自己的国王
5楼-- · 2019-01-08 22:32

If you use the code in the question, you'll want to change the line:

if ((ip.length() < 6) & (ip.length() > 15)) return false;

to

if ((ip.length() <= 6) || (ip.length() > 15)) return false;
查看更多
老娘就宠你
6楼-- · 2019-01-08 22:34
boolean isValid = inetAddressValidator.isValid(hostName) || hostName.equalsIgnoreCase("localhost");

same answer as coobird. Just add localhost to the statement. Most of the environments takes 'localhost' as a valid host name. It is not a ipv4 format but it should be included to consider validity.

查看更多
混吃等死
7楼-- · 2019-01-08 22:35

In think this solution is quite elegant, although it takes a minute to understand it.

The basic idea is to take a sub-string and than validate it.
Please note that I switch x and y, since the start of a sub-string will always be the end of the last one plus 1.

This solution is about 20x faster than a regex variant and 2x faster than splitting.

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;
    }
}

If you know that you'll have a lot wrong IPs consider adding the following code below the first if. This will make the code 1.5x slower but in case of an error improve it by 700x

    for (int i = 0; i < ip.length(); i++) {
        if (!Character.isDigit(ip.charAt(i)) && ip.charAt(i) != '.') return false;
    }
查看更多
登录 后发表回答