6

An IPv4 can have more representations: as string (a.b.c.d) or numerical (as an unsigned int of 32 bits). (Maybe other, but I will ignore them.)

Is there any built in support in Java (8), simple and easy to use, without network access, to convert between these formats?

I need something like this:

long ip = toNumerical("1.2.3.4"); // returns 0x0000000001020304L
String ipv4 = toIPv4(0x0000000001020304L); // returns "1.2.3.4"

If there is no built in such functions in Java, feel free to suggest other solutions.

Thank you

Costin
  • 2,699
  • 5
  • 25
  • 43
  • See this similar question: http://stackoverflow.com/questions/12057853/how-to-convert-string-ip-numbers-to-integer-in-java/12057944#12057944 – gparis Apr 25 '16 at 09:18

4 Answers4

11

The can be done using InetAddress as follows.

//Converts a String that represents an IP to an int.
InetAddress i = InetAddress.getByName(IPString);
int intRepresentation = ByteBuffer.wrap(i.getAddress()).getInt();

//This converts an int representation of ip back to String
i = InetAddress.getByName(String.valueOf(intRepresentation));
String ip = i.getHostAddress();
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
QuakeCore
  • 1,886
  • 2
  • 15
  • 33
  • Will `InetAddresss` do everything locally, without any tentative of network access? Are these conversions arithmetic only? :) – Costin Apr 25 '16 at 09:45
  • Yes the Inetaddress class just represents an Internet Protocol address, so no network access is needed, and what exactly do you mean by arithmetic only? but yah I believe so, the main operations here are built upon bit shifting and stuff.. – QuakeCore Apr 25 '16 at 10:00
  • Instead of arithmetic I should have said "different interpretation of the same bytes". We may read them as numeric, or as String (a.b.c.d) Thanks – Costin Apr 25 '16 at 10:10
  • 5
    Is it ok to use `int`? The IP is `unsigned int`! Isn't it safer to use long? What is the `int` which corresponds to `255.0.0.0`? Can the numerical IP be negative? Am I asking too many questions? :) Thanks – Costin Apr 25 '16 at 10:13
  • This code will throw java.net.UnknownHostException: Unable to resolve host on line: InetAddress.getByName(...) See my answer to properly convert string ip address to int and back to string – Kirill Karmazin Oct 18 '17 at 09:54
  • 1
    Code fails when converting "176.218.221.21" to int since ints are signed data types. – Halil May 05 '20 at 12:32
  • 1
    @QuakeCore Please, edit your answer and wrap ByteBuffer with Integer.toUnsignedLong method in order to support unsigned integer results. ```long longRepresentation = Integer.toUnsignedLong(ByteBuffer.wrap(i.getAddress()).getInt());``` – BeardOverflow Aug 27 '21 at 08:26
  • 2
    @Costin Use com.google.common.net.InetAddresses.forString(String ipString) to avoid any tentative of network access (guava package). The original java.net.InetAddress.getByName(String ipString) would use some DNS lookups for local addresses. – BeardOverflow Aug 27 '21 at 08:35
6

Heres is a way to Convert IP to Number. I found it a valid way to accomplish the task in Java.

public long ipToLong(String ipAddress) {

    String[] ipAddressInArray = ipAddress.split("\\.");

    long result = 0;
    for (int i = 0; i < ipAddressInArray.length; i++) {

        int power = 3 - i;
        int ip = Integer.parseInt(ipAddressInArray[i]);
        result += ip * Math.pow(256, power);

    }

    return result;
  }

This is also how you would implement it in Scala.

  def convertIPToLong(ipAddress: String): Long = {

    val ipAddressInArray = ipAddress.split("\\.")
    var result = 0L

    for (i  <- 0  to ipAddressInArray.length-1) {
      val power = 3 - i
      val ip = ipAddressInArray(i).toInt
      val longIP = (ip * Math.pow(256, power)).toLong
      result = result +longIP
    }
    result
  }
SparkleGoat
  • 503
  • 1
  • 9
  • 22
4

Code snippet provided by QuakeCore will throw "java.net.UnknownHostException: Unable to resolve host" on the part where you want to convert it back to string

but the idea of utilizing InetAddress class is correct. Here is what you want to do:

            try {
                InetAddress inetAddressOrigin = InetAddress.getByName("78.83.228.120");
                int intRepresentation = ByteBuffer.wrap(inetAddressOrigin.getAddress()).getInt(); //1314120824

                ByteBuffer buffer = ByteBuffer.allocate(4);
                buffer.putInt(intRepresentation);
                byte[] b = buffer.array();

                InetAddress inetAddressRestored = InetAddress.getByAddress(b);
                String ip = inetAddressRestored.getHostAddress();//78.83.228.120

            } catch (UnknownHostException e) {
                e.printStackTrace(); //
            }

P.S.: If you will do this for some list of ips, validate them to be sure they don't have subnet masks, for example: 78.83.228.0/8 In this case you will need to flatten them: 78.83.228.0/8 => 78.83.228.0 78.83.228.1 78.83.228.2 78.83.228.3 78.83.228.4 78.83.228.5 78.83.228.6 78.83.228.7

Kirill Karmazin
  • 6,256
  • 2
  • 54
  • 42
  • 1
    Nice try but there seems to be some bug/problem here. Try your code with these IPs: `191.255.255.254`, `252.250.250.254`, `255.250.250.254`. You get signed integers. For example, the first one (`191.255.255.254`) should convert to 3221225470 but it gives `-1073741826` – papigee Sep 17 '19 at 16:58
2

I would suggest:

long ip2long() {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES).order(ByteOrder.BIG_ENDIAN);
    buffer.put(new byte[] { 0,0,0,0 });
    buffer.put(socket.getInetAddress().getAddress());
    buffer.position(0);
    return buffer.getLong();
}
Ahmed Ashour
  • 5,179
  • 10
  • 35
  • 56
Amir Fo
  • 5,163
  • 1
  • 43
  • 51