【问题标题】:IPV6 address into compressed form in Java用Java压缩成IPV6地址
【发布时间】:2011-10-26 00:25:21
【问题描述】:

我使用Inet6Address.getByName("2001:db8:0:0:0:0:2:1").toString()方法压缩IPv6地址,输出为2001:db8:0:0:0:0:2:1,但我需要2001:db8::2:1。 , 基本上压缩输出应该基于RFC 5952 standard, 也就是

  1. Shorten as Much as Possible :例如,2001:db8:0:0:0:0:2:1 必须缩短为
    2001:db8::2:1。同样,2001:db8::0:1 是不可接受的, 因为符号“::”可以用来产生一个 更短的表示 2001:db8::1。

  2. Handling One 16-Bit 0 Field:符号“::”不得仅用于缩短一个 16 位 0 字段。 例如,表示 2001:db8:0:1:1:1:1:1 是正确的,但是 2001:db8::1:1:1:1:1 不正确。

  3. Choice in Placement of "::" : = 如果在“::”的位置上有其他选择,则 最长的连续 16 位 0 字段必须缩短(即, 具有三个连续零字段的序列在 2001 年被缩短: 0:0:1:0:0:0:1)。当连续 16 位 0 字段的长度 相等(即 2001:db8:0:0:1:0:0:1),第一个零序列 位必须缩短。例如 2001:db8::1:0:0:1 是正确的 表示。

我还检查了 another post in Stack overflow,但没有指定条件(示例选择 :: 的位置)。

是否有任何 java 库来处理这个问题?谁能帮帮我?

提前致谢。

【问题讨论】:

    标签: java regex ipv6 regex-negation


    【解决方案1】:

    这个怎么样?

    String resultString = subjectString.replaceAll("((?::0\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)", "::$2").replaceFirst("^0::","::");
    

    没有Java双反斜杠地狱的解释:

    (       # Match and capture in backreference 1:
     (?:    #  Match this group:
      :0    #  :0
      \b    #  word boundary
     ){2,}  # twice or more
    )       # End of capturing group 1
    :?      # Match a : if present (not at the end of the address)
    (?!     # Now assert that we can't match the following here:
     \S*    #  Any non-space character sequence
     \b     #  word boundary
     \1     #  the previous match
     :0     #  followed by another :0
     \b     #  word boundary
    )       # End of lookahead. This ensures that there is not a longer
            # sequence of ":0"s in this address.
    (\S*)   # Capture the rest of the address in backreference 2.
            # This is necessary to jump over any sequences of ":0"s
            # that are of the same length as the first one.
    

    输入:

    2001:db8:0:0:0:0:2:1
    2001:db8:0:1:1:1:1:1
    2001:0:0:1:0:0:0:1
    2001:db8:0:0:1:0:0:1
    2001:db8:0:0:1:0:0:0
    

    输出:

    2001:db8::2:1
    2001:db8:0:1:1:1:1:1
    2001:0:0:1::1
    2001:db8::1:0:0:1
    2001:db8:0:0:1::
    

    (我希望最后一个例子是正确的——或者如果地址以0结尾,还有其他规则吗?)

    【讨论】:

    • 这在组有前导零时不起作用。例如。 2001:0db8:0:0000:00:000:0002:0000 -> 2001:db8::2:0。在使用正则表达式压缩它之前,我可以通过消除这些前导零来轻松解决这个问题。但是有一种方法可以在一个正则表达式中做到这一点?
    • 0:0:0:0:5:6:7:8 变为 0::5:6:7:8。我认为应该改为::5:6:7:8。所以在最后加上.replaceFirst("^0::","::")
    【解决方案2】:

    我最近遇到了同样的问题,希望(非常轻微地)改进蒂姆的回答。

    以下正则表达式有两个优点:

    ((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)

    首先,它结合了匹配多个零的更改。其次,它还能正确匹配地址开头最长的零链的地址(例如0:0:0:0:0:0:0:1)。

    【讨论】:

    • 虽然这个正则表达式处理像“0:0:0:0:0:0:0:0”这样的地址并且正确地将它缩短为“::”,它不再匹配最长的组零(即它错误地将“0:0:1:0:0:0:0:0”缩短为“::1:0:0:0:0:0”而不是“0:0:1:: "。
    • 这会将0000:0000:0000:0000:0000:0000:0000:0001 压缩为::0001 而不是::1
    【解决方案3】:

    java-ipv6 几乎就是你想要的。从 0.10 版开始,它不会检查是否用 :: 缩短零的最长运行 - 例如 0:0:1:: 缩短为 ::1:0:0:0:0:0。不过,对于处理 IPv6 地址来说,它是一个非常不错的库,而且这个问题应该是 fixed with version 0.11,因此该库是 RFC 5952 compliant

    【讨论】:

      【解决方案4】:

      在进行了一些测试后,我认为以下内容涵盖了所有不同的 IPv6 场景:

      "((?:(?::0|0:0?)\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)" -> "::$2"
      

      【讨论】:

        【解决方案5】:

        Guava 的 InetAddresses 类具有 toAddrString(),其格式符合 RFC 5952。

        【讨论】:

          【解决方案6】:

          The open-source IPAddress Java library 可以像描述的那样做,它提供了多种为 IPv4 和/或 IPv6 生成字符串的方法,包括 IPv6 匹配 rfc 5952 的规范字符串。免责声明:我是该库的项目经理。

          使用您列出的示例,示例代码是:

              IPAddress addr = new IPAddressString("2001:db8:0:0:0:0:2:1").getAddress();
              System.out.println(addr.toCanonicalString());
              // 2001:db8::2:1
              addr = new IPAddressString("2001:db8:0:1:1:1:1:1").getAddress();
              System.out.println(addr.toCanonicalString());
              // 2001:db8:0:1:1:1:1:1
              addr = new IPAddressString("2001:0:0:1:0:0:0:1").getAddress();
              System.out.println(addr.toCanonicalString());
              // 2001:0:0:1::1
              addr = new IPAddressString("2001:db8:0:0:1:0:0:1").getAddress();
              System.out.println(addr.toCanonicalString());
              //2001:db8::1:0:0:1
          

          【讨论】:

            【解决方案7】:

            不太优雅,但这是我的建议(基于 chrixm 工作):

            public static String shortIpv6Form(String fullIP) {
                    fullIP = fullIP.replaceAll("^0{1,3}", "");
                    fullIP = fullIP.replaceAll("(:0{1,3})", ":");
                    fullIP = fullIP.replaceAll("(0{4}:)", "0:");
                    //now we have full form without unnecessaires zeros
                    //Ex:
                    //0000:1200:0000:0000:0000:0000:0000:0000 -> 0:1200:0:0:0:0:0:0
                    //0000:0000:0000:1200:0000:0000:0000:8351 -> 0:0:0:1200:0:0:0:8351
                    //0000:125f:0000:94dd:e53f:0000:61a9:0000 -> 0:125f:0:94dd:e53f:0:61a9:0
                    //0000:005f:0000:94dd:0000:cfe7:0000:8351 -> 0:5f:0:94dd:0:cfe7:0:8351
            
            
                    //compress to short notation
                    fullIP = fullIP.replaceAll("((?:(?:^|:)0+\\b){2,}):?(?!\\S*\\b\\1:0+\\b)(\\S*)", "::$2");
            
                    return fullIP;
                }
            
            1. 结果:

              7469:125f:8eb6:94dd:e53f:cfe7:61a9:8351 -> 7469:125f:8eb6:94dd:e53f:cfe7:61a9:8351 7469:125f:0000:0000:e53f:cfe7:0000:0000 -> 7469:125f::e53f:cfe7:0:0 7469:125f:0000:0000:000f:c000:0000:0000 -> 7469:125f::f:c000:0:0 7469:125f:0000:0000:000f:c000:0000:0000 -> 7469:125f::f:c000:0:0 7469:0000:0000:94dd:0000:0000:0000:8351 -> 7469:0:0:94dd::8351 0469:125f:8eb6:94dd:0000:cfe7:61a9:8351 -> 469:125f:8eb6:94dd:0:cfe7:61a9:8351 0069:125f:8eb6:94dd:0000:cfe7:61a9:8351 -> 69:125f:8eb6:94dd:0:cfe7:61a9:8351 0009:125f:8eb6:94dd:0000:cfe7:61a9:8351 -> 9:125f:8eb6:94dd:0:cfe7:61a9:8351 0000:0000:8eb6:94dd:e53f:0007:6009:8350 -> ::8eb6:94dd:e53f:7:6009:8350 0000:0000:8eb6:94dd:e53f:0007:6009:8300 -> ::8eb6:94dd:e53f:7:6009:8300 0000:0000:8eb6:94dd:e53f:0007:6009:8000 -> ::8eb6:94dd:e53f:7:6009:8000 7469:0000:0000:0000:e53f:0000:0000:8300 -> 7469::e53f:0:0:8300 7009:100f:8eb6:94dd:e000:cfe7:6009:8351 -> 7009:100f:8eb6:94dd:e000:cfe7:6009:8351 7469:100f:8006:900d:e53f:cfe7:61a9:8351 -> 7469:100f:8006:900d:e53f:cfe7:61a9:8351 7000:1200:8e00:94dd:e53f:cfe7:0000:0001 -> 7000:1200:8e00:94dd:e53f:cfe7:0:1 0000:0000:0000:0000:0000:0000:0000:0000 -> :: 0000:0000:0000:94dd:0000:0000:0000:0000 -> 0:0:0:94dd:: 0000:1200:0000:0000:0000:0000:0000:0000 -> 0:1200:: 0000:0000:0000:1200:0000:0000:0000:8351 -> ::1200:0:0:0:8351 0000:125f:0000:94dd:e53f:0000:61a9:0000 -> 0:125f:0:94dd:e53f:0:61a9:0 7469:0000:8eb6:0000:e53f:0000:61a9:0000 -> 7469:0:8eb6:0:e53f:0:61a9:0 0000:125f:0000:94dd:0000:cfe7:0000:8351 -> 0:125f:0:94dd:0:cfe7:0:8351 0000:025f:0000:94dd:0000:cfe7:0000:8351 -> 0:25f:0:94dd:0:cfe7:0:8351 0000:005f:0000:94dd:0000:cfe7:0000:8351 -> 0:5f:0:94dd:0:cfe7:0:8351 0000:000f:0000:94dd:0000:cfe7:0000:8351 -> 0:f:0:94dd:0:cfe7:0:8351 0000:0000:0000:0000:0000:0000:0000:0001 -> ::1

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2017-11-09
              • 1970-01-01
              • 2011-04-15
              • 1970-01-01
              • 1970-01-01
              • 2014-11-15
              • 2011-10-20
              • 2015-04-01
              相关资源
              最近更新 更多