2
votes

Basically, I'm trying to check if a String is a valid IP address without using external libraries in Java (it doesn't have to be an IP with a working host at the other end; it can be an unused one too). I can't check if it's an IP address because I would like DNS support as well. Since the following options are valid:

  • 1.2.3.4:55555
  • localhost:1
  • google.com:12345
  • 1.2.abc:54321 (is this valid?)

but the following aren't valid:

  • 1.2.3.4 (no port)
  • 1.2:34 (not an IP address)
  • local host:12345 (space)
  • 8.8.8.8:abc (not numbers in port slot)
  • stackoverflow.com:234.5 (basically only numbers should follow the :
  • localhost:65536 (port number out of bounds)

At this moment (I will continue to update this), i do the following checks:

host != null;
!host.contains(" ");
host.contains(":");

Other checks I think can be done but I don't know how to do:

*Contains 1 and only 1 colon *If it only contains numbers and periods, it must contain 3 and only 3 periods, 4 numbers, and each number has to be between 0 and 255 *Number following colon is a number and is between 0 and 65535

Thank you!

1

1 Answers

9
votes

I would use a regex like this :

import java.util.regex.Pattern;

public class IpCheck {

    public static void main(String[] args) {

        Pattern p = Pattern.compile("^"
                + "(((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{2,6}" // Domain name
                + "|"
                + "localhost" // localhost
                + "|"
                + "(([0-9]{1,3}\\.){3})[0-9]{1,3})" // Ip
                + ":"
                + "[0-9]{1,5}$"); // Port

        System.out.println(p.matcher("1.2.3.4:55555").matches());
        System.out.println(p.matcher("localhost:1").matches());
        System.out.println(p.matcher("google.com:12345").matches());
        System.out.println(p.matcher("1.2.abc:54321").matches());

        System.out.println(p.matcher("1.2.3.4").matches());
        System.out.println(p.matcher("1.2:34").matches());
        System.out.println(p.matcher("local host:12345").matches());
        System.out.println(p.matcher("stackoverflow.com:234.5").matches());
        System.out.println(p.matcher("localhost:65536").matches());

    }

}

Prints :

true
true
true
true
false
false
false
false
true

It works except for the port range, for this I would suggest that you extract the port number if any, and outside the regex. My opinion is that Regex is not made to test integers range (still possible)