如何在Java中将字符串(IP地址)转换为整数

13

示例:

// using Integer.parseInt
int i = Integer.parseInt("123");

你怎样才能做到相同的效果?

// using Integer.parseInt
int i = Integer.parseInt("123.45.55.34");

请问您为什么需要那个? - Subhrajyoti Majumder
1
你可以使用此表达式返回的hashCode(),但这有点像是一个hack。 - Peter Lawrey
1
你最近的编辑使大部分答案变得无用。请在进行重大语义更改时考虑提出新问题。 - Lukas Eder
Lu先生,感谢您的评论,不过所有的答案都很有帮助 :) - Brane
我同意Mike的看法,现在这个问题似乎不太清楚。 - Hi computer
显示剩余4条评论
8个回答

20

你可能想要这样做:

// Parse IP parts into an int array
int[] ip = new int[4];
String[] parts = "123.45.55.34".split("\\.");

for (int i = 0; i < 4; i++) {
    ip[i] = Integer.parseInt(parts[i]);
}

或者这样:

// Add the above IP parts into an int number representing your IP 
// in a 32-bit binary form
long ipNumbers = 0;
for (int i = 0; i < 4; i++) {
    ipNumbers += ip[i] << (24 - (8 * i));
}

当然,正如其他人建议的,使用InetAddress可能比自己编写更合适...


这也是我认为他想知道的。 - Kai Huppmann
1
@KaI:是的,这就是所谓的有根据的猜测 :-) - Lukas Eder
@LukasEder 谢谢您的回复,我在解析查询中的点分IP数字方面遇到了问题。我已经更新了我的问题 :) - Brane
@ :) 这是我开始解释的最简单方式, :) - Brane
2
当然,你会想要使用 long,否则你将会溢出 int 并且对于任何大于 127.255.255.255 的 IP 地址得到错误的值。;-) - Aaron Blenkush

20

对于IPv4地址,您可以这样做,因为部分只是整数版本的四个字节。

要将InetAddress转换为其整数表示,请执行以下操作:

int result = 0;  
for (byte b: inetAdress.getAddress())  
{  
    result = result << 8 | (b & 0xFF);  
}

请注意,现在不应该使用32位整数来表示IP地址,因为我们正在进入IPV6地址的时代。

编辑:要在Java中将类似于“123.45.55.34”这样的字符串解析为有用的内容,可以使用InetAddress.getByName(yourString)


你好@dystroy,您提供的代码如何适用于我的问题?我对问题有更多的细节。谢谢先生 :) - Brane
这是一个非常不同的问题。我编辑了我的答案,但现在开始变得混乱了... - Denys Séguret
3
如果你只是想解析一个IP地址,使用getByName可能不是一个好主意,因为如果你给出的是主机名,那么你将突然进行同步网络I/O。 - Glenn Maynard

8

IPAddress Java库以多态方式支持IPv4和IPv6。免责声明:我是该库的项目经理。

下面的代码适用于IPv4和IPv6地址。使用您的IPv4地址示例:

IPAddress addr = new IPAddressString("123.45.55.34").getAddress();
BigInteger value = addr.getValue(); // 2066560802

如果是IPv4地址,您可以直接使用一个整数值:
if(addr.isIPv4()) {
    int val = addr.toIPv4().intValue(); // 2066560802
}

7

您需要意识到,形式为123.45.55.34的IPv4地址实际上是代表地址的每个字节的4个三位数字。一次解析整个字符串不起作用。

其他人提到使用InetAddress,但如果您只有IP的字符串表示形式,则据我所知无法轻松地实例化InetAddress

您可以执行以下操作:

public static int parseIp(String address) {
    int result = 0;

    // iterate over each octet
    for(String part : address.split(Pattern.quote("."))) {
        // shift the previously parsed bits over by 1 byte
        result = result << 8;
        // set the low order bits to the current octet
        result |= Integer.parseInt(part);
    }
    return result;
}

八进制?就像 192.168.0.1 这样的吗?;-) - Lukas Eder
@LukasEder,哇,我一定是糊涂了。我修正了答案,感谢你的提醒。 - Mike Deck
好吧,短暂的一刻,我自己也有些担心,是否有什么事情从我的记忆中溜走了;-) - Lukas Eder

3
System.out.println(
        ByteBuffer.allocate(Integer.BYTES)
        .put(InetAddress.getByName("0.0.1.0").getAddress())
        .getInt(0));

输出:

256


1
我认为您可能误解了自己的问题。您是想将其转换为单个整数值吗?如果是这样,那么您的问题前提是错误的,因为IP地址不是一个数字,而是多个字节值。它不是123,456,789,000,而是字节123、字节455、字节789和字节000。我知道这些不是真正的字节数字,但重点是这不是1230亿4560万789千000。在我的看来,您正在将整个内容视为单个整数,但这在IP地址中并不是这样。

0

抱歉重新打开一个旧问题,但对我来说似乎缺少一个可能的有效和高效的解决方案:

static int ipV4ToInt(int a1, int a2, int a3, int a4){
  return (a1 << 24) ^ (a2 << 16) ^ (a3 << 8) ^ a4;
}

然后你可以添加解析和验证:
class MyAwesomeIPv4Utils {
  private MyAwesomeIPv4Utils(){} // It's a library, sorry OOP addicted...

  static int validateIpPart(int n){
    if (n < 0 || n > 255)
      throw new IllegalArgumentException("Invalid IP v4 part: " + n);
    return n;
  }
  
  static int validateIpPart(String p){
    return validateIpPart(Integer.parseInt(p));
  }
  
  static int internalIpV4ToInt(int a1, int a2, int a3, int a4){
    // let validation outside, just for performance reasons (e.g. inlining and lazy evaluation): it can be made by the caller
    return (a1 << 24) ^ (a2 << 16) ^ (a3 << 8) ^ a4;
  }
  
  // this can be made public as it handles the validation, and can be used to directly create int when you know the addresses at comple time
  public static int ipV4ToInt(int a1, int a2, int a3, int a4){
    return internalIpV4ToInt(
      validateIpPart(a1),
      validateIpPart(a2),
      validateIpPart(a3),
      validateIpPart(a4)
    );
  }
  
  // this can be exposed too, as it handles both validation and parsing
  public static int ipV4ToInt(String ipStr){
    Objects.requireNonNull(ipStr, "null IP Address");
    // If you prefer you can make this Pattern a static variable, to create it just once and shared (Patterns are thread-safe), but be careful with it's instantiation as it can be null at the first invokation of this static method
    final Pattern ipPattern = Pattern.compile("(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})");
    final Matcher m = ipPattern.matcher(ipStr);
    if (!m.matches())
      throw new IllegalArgumentException("Invalid IP v4 address: " + ipStr);

    return internalIpV4ToInt(
      validateIpPart(m.group(1)),
      validateIpPart(m.group(2)),
      validateIpPart(m.group(3)),
      validateIpPart(m.group(4))
    );
  }
}

抱歉,但是你最后的修改使得代码更难阅读/理解,没有帮助,并且可能没有真正的优势。 - undefined

-1

IPAddressUtil#textToNumericFormatV4 的性能要优于 String#split 来获取IP地址的字节,此外它还会检查IP地址是否有效。

 public int intOfIpV4(String ip) {
        int result = 0;
        byte[] bytes = IPAddressUtil.textToNumericFormatV4(ip);
        if (bytes == null) {
            return result;
        }
        for (byte b : bytes) {
            result = result << 8 | (b & 0xFF);
        }
        return result;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接