22

Using the standard Java libraries, what is the quickest way to get from the dotted string representation of an IPV4-address ("127.0.0.1") to the equivalent integer representation (2130706433).

And correspondingly, what is the quickest way to invert said operation - going from the integer 2130706433 to the string representation"127.0.0.1"?

knorv
  • 49,059
  • 74
  • 210
  • 294

7 Answers7

34

String to int:

int pack(byte[] bytes) {
  int val = 0;
  for (int i = 0; i < bytes.length; i++) {
    val <<= 8;
    val |= bytes[i] & 0xff;
  }
  return val;
}

pack(InetAddress.getByName(dottedString).getAddress());

Int to string:

byte[] unpack(int bytes) {
  return new byte[] {
    (byte)((bytes >>> 24) & 0xff),
    (byte)((bytes >>> 16) & 0xff),
    (byte)((bytes >>>  8) & 0xff),
    (byte)((bytes       ) & 0xff)
  };
}


InetAddress.getByAddress(unpack(packedBytes)).getHostAddress()
Geoff Reedy
  • 34,891
  • 3
  • 56
  • 79
  • 2
    127.0.0.1 gives 2130706433, but 255.255.255.255 doesn't give 4294967295. signed vs. unsigned problem? – knorv Feb 11 '10 at 00:53
  • 5
    To print as unsigned cast the result as long and mask off the high bits: `((long)packedBytes)&0xffffffff` – Geoff Reedy Feb 11 '10 at 02:50
  • 1
    byte in Java is up to 2^7-1 so that each byte won't be able to display any integer large than 127. The right approach is to use int to store the digit. – zhaocong Nov 19 '13 at 08:20
30

You can also use the Google Guava InetAddress Class

String ip = "192.168.0.1";
InetAddress addr = InetAddresses.forString(ip);
// Convert to int
int address = InetAddresses.coerceToInteger(addr);
// Back to str 
String addressStr = InetAddresses.fromInteger(address));
Iulian Popescu
  • 2,595
  • 4
  • 23
  • 31
Ido
  • 573
  • 4
  • 11
  • 2
    I think this is the simplest. Unless you are concerned with micro-seconds performance use the standard libraries which handles all the endians and signs – Ganesh Krishnan Jan 22 '16 at 08:59
11

I've modified my original answer. In Sun's implementation of InetAddress, the hashCode method produces the integer representation of the IPv4 address, but as the commenters correctly pointed out, this is not guaranteed by the JavaDoc. Therefore, I decided to use the ByteBuffer class to calculate the value of the IPv4 address instead.

import java.net.InetAddress;
import java.nio.ByteBuffer;

// ...

try {
    // Convert from integer to an IPv4 address
    InetAddress foo = InetAddress.getByName("2130706433");
    String address = foo.getHostAddress();
    System.out.println(address);

    // Convert from an IPv4 address to an integer
    InetAddress bar = InetAddress.getByName("127.0.0.1");
    int value = ByteBuffer.wrap(bar.getAddress()).getInt();
    System.out.println(value);

} catch (Exception e) {
    e.printStackTrace();
}

The output will be:

127.0.0.1
2130706433
William Brendel
  • 31,712
  • 14
  • 72
  • 77
  • 1
    Is the hashCode() well-defined as doing a 4-byte to int conversion ? If not, I suspect that's the case. An explanation is always good, mind. – Brian Agnew Feb 11 '10 at 00:03
  • The mapping from IP address to int needs to be a bijection. hashCode does not guarantee this. – President James K. Polk Feb 11 '10 at 00:05
  • This should be downvoted. Nothing in the Javadocs guarantees this behavior, it just happens to be the (sensible) Sun implementation at the moment. Sun could change this to just return a constant and it would still behave correctly, but your example would fail. – President James K. Polk Feb 11 '10 at 00:15
  • You're correct that InetAddress's hashCode() method does not specify how the hash is computed. I'll leave the answer here since it does "work" using the standard implementation of InetAddress. – William Brendel Feb 11 '10 at 00:16
  • I've updated my answer based on your concerns. My example now uses the ByteBuffer class to calculate the integer value of an IPv4 address instead of relying on InetAddress's hashCode method. – William Brendel Feb 11 '10 at 00:33
4

In case you need to learn the long hand math, you can use Substr to rip out the octets. Mutliply the first octet signifying the Class by (256*256*256) or (2^24) second multiplied by (256*256) (2^16) third multiplied by (256) (2^8) fourth multiplied by 1 or (2^0)

127 * (2^24) + 0 *(2^16) + 0 * (2^8) + 1 * (2^0) 2130706432 + 0 + 0 + 1 = 2130706433

3

Using the IPAddress Java library it is simple, one line of code for each direction. Disclaimer: I am the project manager of that library.

    IPv4Address loopback = new IPAddressString("127.0.0.1").getAddress().toIPv4();
    System.out.println(loopback.intValue());
    IPv4Address backAgain = new IPv4Address(loopback.intValue());
    System.out.println(backAgain);

Output:

    2130706433
    127.0.0.1
Sean F
  • 4,344
  • 16
  • 30
2

I've not tried it wrt. performance, but the simplest way is probably to use the NIO ByteBuffer.

e.g.

 byteBuffer.put(integer).array();

would return you a byte array representing the integer. You may need to modify the byte order.

Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
  • why not just pick a byte order and make it the byte order of the ByteBuffer? Then you wouldn't have to worry about different default byte orders on different machines. EDIT: nevermind, the default is Big endian. – President James K. Polk Feb 10 '10 at 23:58
1

Another way:

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