2010-02-10 70 views
16

使用标准Java库,从IPV4地址("127.0.0.1")的虚线字符串表示法到等效整数表示法(2130706433)的最快方式是什么?从127.0.0.1到2130706433,再返回

相应地,什么是反转所述操作的最快方法 - 从整数2130706433到字符串表示"127.0.0.1"

回答

25

字符串为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()); 

诠释字符串:

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() 
+2

127.0.0.1给出2130706433,但255.255.255.255不给出4294967295.签名与未签名问题? – knorv 2010-02-11 00:53:19

+4

要以unsigned形式打印结果,并屏蔽掉高位:'((long)packedBytes)&0xffffffff' – 2010-02-11 02:50:39

+0

Java中的字节最大为2^7-1,因此每个字节将不能显示任何字节整数大于127.正确的方法是使用int来存储数字。 – zhaocong 2013-11-19 08:20:54

2

我还没试过。性能,但最简单的方法可能是使用NIO ByteBuffer

例如

byteBuffer.put(integer).array(); 

会返回一个表示整数的字节数组。你可能需要修改字节顺序。

+0

为什么不选择一个字节顺序,并使其字节缓冲区的字节顺序?那么你不必担心不同机器上的不同默认字节顺序。编辑:没关系,默认是Big endian。 – 2010-02-10 23:58:39

9

我修改了我原来的答案。在Sun的InetAddress的实现中,hashCode方法产生IPv4地址的整数表示,但正如评论者正确指出的那样,JavaDoc并不能保证这一点。因此,我决定使用ByteBuffer类来计算IPv4地址的值。

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

输出将是:

127.0.0.1 
2130706433 
+1

散列码()是否定义为4字节到int的转换?如果不是,我怀疑是这样。一个解释总是很好,心灵。 – 2010-02-11 00:03:16

+0

从IP地址到int的映射需要是双向映射。 hashCode不保证这一点。 – 2010-02-11 00:05:48

+0

这应该是downvoted。 Javadocs中没有任何内容保证这种行为,它恰好是目前的(明智的)Sun实施。 Sun可以改变这个只是返回一个常量,它仍然会正常工作,但是你的例子会失败。 – 2010-02-11 00:15:04

3

如果你需要学习的长手数学,你可以使用Substr来翻译八位字节。 (256 * 256 * 256)或(2^24) 第二个乘以(256 * 256)(2^16) 第三个乘以(256)(2^8) 第四个八位位组表示第一个八位字节乘以1或(2^0)

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

27

还可以使用Google Guava InetAddress

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)); 
+2

我认为这是最简单的。除非你关心微秒性能,否则使用标准库来处理所有的endians和符号 – 2016-01-22 08:59:50

0

的另一种方法:

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

使用the IPAddress Java 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); 

输出:

2130706433 
    127.0.0.1