【问题标题】:Java: convert int to InetAddressJava:将 int 转换为 InetAddress
【发布时间】:2010-12-29 18:45:57
【问题描述】:

我有一个int,其中包含一个按网络字节顺序排列的 IP 地址,我想将其转换为一个InetAddress 对象。我看到有一个InetAddress 构造函数接受byte[],是否需要先将int 转换为byte[],还是有其他方法?

【问题讨论】:

  • 你能举一个例子,这个 int 是什么样子的,它的字符串表示应该是什么样子的?我无法想象如何将 255255255255 放入 int 中,它会溢出。
  • @BalusC:IPv4 地址只是一个 32 位数字,只是它通常表示为 4 个 8 位值。不过,这些信息非常适合 32 位。
  • 请记住,如果您想支持 IPv6,则不能使用单个 int 来处理 IP 地址。

标签: java inetaddress


【解决方案1】:

测试和工作:

int ip  = ... ;
String ipStr = 
  String.format("%d.%d.%d.%d",
         (ip & 0xff),   
         (ip >> 8 & 0xff),             
         (ip >> 16 & 0xff),    
         (ip >> 24 & 0xff));

【讨论】:

  • 这会以错误的顺序转换字节。它适用于小端整数,但问题是关于“网络字节顺序”,它是大端的,就像 Java 中的整数一样。正确的顺序是:String.format("%d.%d.%d.%d", (ip >> 24 & 0xff), (ip >> 16 & 0xff), (ip >> 8 & 0xff), (ip & 0xff));
【解决方案2】:

这应该可行:

int ipAddress = ....
byte[] bytes = BigInteger.valueOf(ipAddress).toByteArray();
InetAddress address = InetAddress.getByAddress(bytes);

您可能需要交换字节数组的顺序,我无法确定数组是否会以正确的顺序生成。

【讨论】:

  • 这确实仍然需要交换字节数组的顺序。然而,事实证明我的输入实际上是按主机顺序排列的!谢谢。
  • 不适用于 0.0.0.0 - 0.127.255.255 和 255.128.0.0 - 255.255.255.255 范围内的地址:bytes 的元素少于 4 个
  • @NikolayKuznetsov 因为这些范围会产生大小为 3 或更小的字节数组,而 InetAddress 要求数组大小为 4 或 16。
  • 危险。不起作用,例如 0.0.0.0。不可靠!
【解决方案3】:

我觉得这段代码比较简单:

static public byte[] toIPByteArray(int addr){
        return new byte[]{(byte)addr,(byte)(addr>>>8),(byte)(addr>>>16),(byte)(addr>>>24)};
    }

static public InetAddress toInetAddress(int addr){
    try {
        return InetAddress.getByAddress(toIPByteArray(addr));
    } catch (UnknownHostException e) {
        //should never happen
        return null;
    }
}

【讨论】:

【解决方案4】:

如果您使用的是 Google 的 Guava 库,InetAddresses.fromInteger 完全可以满足您的需求。 Api 文档是here

如果您更愿意编写自己的转换函数,您可以按照@aalmeida 的建议执行操作,但请确保将字节按正确的顺序排列(最重要的字节在前)。

【讨论】:

  • 您答案中的链接已损坏
  • @redbeam_ 已更新。
【解决方案5】:
public static byte[] int32toBytes(int hex) {
    byte[] b = new byte[4];
    b[0] = (byte) ((hex & 0xFF000000) >> 24);
    b[1] = (byte) ((hex & 0x00FF0000) >> 16);
    b[2] = (byte) ((hex & 0x0000FF00) >> 8);
    b[3] = (byte) (hex & 0x000000FF);
    return b;

}

你可以使用这个函数将int转换为字节;

【讨论】:

    【解决方案6】:

    没有足够的声誉来评论 skaffman 的答案,所以我将其添加为单独的答案。

    skaffman 提出的解决方案是正确的,但有一个例外。 BigInteger.toByteArray() 返回一个字节数组,它可能有一个前导符号位。

    byte[] bytes = bigInteger.toByteArray();
    
    byte[] inetAddressBytes;
    
    // Should be 4 (IPv4) or 16 (IPv6) bytes long
    if (bytes.length == 5 || bytes.length == 17) {
        // Remove byte with most significant bit.
        inetAddressBytes = ArrayUtils.remove(bytes, 0);
    } else {
        inetAddressBytes = bytes;
    }
    
    InetAddress address = InetAddress.getByAddress(inetAddressBytes);
    

    PS 上面的代码使用了 Apache Commons Lang 的 ArrayUtils。

    【讨论】:

    • 我认为额外的前导符号位不会有问题,但如果地址在 0.0.0.0 - 0.127.255.255 和 255.128.0.0 - 255.255.255.255 范围内,则会丢失字节跨度>
    • 对不起,我不是这个领域的专家。你能详细说明你的评论吗?恐怕我错过了重点(并且可能在我的代码中存在错误;))。
    • @DennisLaumen 你会的。例如,尝试 0、42 或 -42。您应该得到 0.0.0.0、0.0.0.42 和 255.255.255.214。相反,你会得到一个例外。另见en.wikipedia.org/wiki/Twos_complement
    【解决方案7】:

    使用谷歌番石榴:

    byte[] bytes =Ints.toByteArray(ipAddress);

    InetAddress 地址 = InetAddress.getByAddress(bytes);

    【讨论】:

      【解决方案8】:

      由于无法格式化 cmets,让我贴出源自@Mr.KevinThomas 评论的代码:

      if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
          ipAddress = Integer.reverseBytes(ipAddress);
      }
      sReturn = String.format(Locale.US, "%d.%d.%d.%d", (ipAddress >> 24 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 8 & 0xff), (ipAddress & 0xff));
      

      已在 Android 上测试。

      【讨论】:

        【解决方案9】:

        这个可以试试

        public static String intToIp(int i) { return ((i >> 24 ) & 0xFF) + "." + ((i >> 16 ) & 0xFF) + "." + ((i >> 8 ) & 0xFF) + "." + ( i & 0xFF); }

        【讨论】:

        • 他要求的是 int-to-bytearray,而不是 int-to-string。你的话“这可能会起作用”让我觉得你只是用谷歌搜索盲目和复制粘贴的随机函数?为什么?
        【解决方案10】:
          public InetAddress intToInetAddress(Integer value) throws UnknownHostException
          {
            ByteBuffer buffer = ByteBuffer.allocate(32);
            buffer.putInt(value);
            buffer.position(0);
            byte[] bytes = new byte[4];
            buffer.get(bytes);
            return InetAddress.getByAddress(bytes);
          }
        

        【讨论】:

          猜你喜欢
          • 2015-01-17
          • 2013-10-16
          • 2011-07-31
          • 2013-06-02
          • 2020-11-21
          • 1970-01-01
          • 1970-01-01
          • 2014-05-04
          • 2021-01-27
          相关资源
          最近更新 更多