IPV6地址压缩成Java格式



我使用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标准,即

  1. 尽量缩短:例如,2001:db8:0:0:0:0:2:1必须缩短为
    2001: db8:: 2:1。同样,2001:db8::0:1是不可接受的,因为符号"::"可以用来制造一个较短的表示2001:db8::1.

  2. 处理一个16位0字段:符号": "MUST不能用来缩短一个16位0字段。例如,表示2001:db8:0:1:1:1:1: 1:1是正确的,但是2001:db8::1:1:1:1:1不正确。

  3. "::"的位置选择: =当"::&quot的位置有其他选择时必须缩短连续16位0字段的最长运行时间(即:包含三个连续零字段的序列在2001年被缩短:0:0:1:0:0:0:1)。当0字段的长度连续为16位时是相等的(即2001:db8:0:0:1:0:0:1),第一个序列为0比特必须缩短。例如:2001:db8::1:0:0:1表示。

我也检查了 Stack overflow的另一个帖子,但是没有指定条件(示例选择放置::)。

是否有任何java库来处理这个?有人能帮帮我吗?

提前感谢。

这个怎么样?

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结尾是否有另一个规则?)

我最近遇到了同样的问题,并希望(非常轻微)改进Tim的答案。

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

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

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

Guava的InetAddresses类有toAddrString(),它的格式根据RFC 5952。

java-ipv6几乎就是你想要的。从0.10版本开始,它不再检查可以用::缩短的最长零运行时间——例如0:0:1::被缩短为::1:0:0:0:0。对于处理IPv6地址来说,它是一个非常不错的库,但是,这个问题应该在0.11版本中修复,这样库就符合RFC 5952。

开源的IPAddress Java库可以按照描述的那样做,它提供了许多生成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

不太优雅,但这是我的建议(基于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: 8 eb6:94dd: e53f: cfe7:61a9:8351 ->7469:125f: 8 eb6:94dd: e53f: cfe7:61a9:83517469:125f:0000:000:e53f:cfe7:0000:000 -> 7469:125f::e53f:cfe7:0:07469:125f: 00000000000f:c000: 00000000 -> 7469:125f::f:c000:0:07469:125f: 00000000000f:c000: 00000000 -> 7469:125f::f:c000:0:07469: 00:0:94 dd: 00:00:00:8351 -> 7469:0:0:94dd::83510469:125f: 8 eb6:94dd: 0000: cfe7:61a9:8351 ->469:125f: 8 eb6:94dd: 0: cfe7:61a9:83510069:125f: 8 eb6:94dd: 0000: cfe7:61a9:8351 ->69:125f: 8 eb6:94dd: 0: cfe7:61a9:83510009:125f: 8 eb6:94dd: 0000: cfe7:61a9:8351 ->9:125f: 8 eb6:94dd: 0: cfe7:61a9:83510000:0000:8eb6:94dd: e53f: 0007:6009:8350 ->:: 8 eb6:94dd: e53f: 7:6009:8350 0000:0000:8eb6:94dd: e53f: 0007:6009:8300->::8eb6:94dd:e53f: 7:00 00: 8300 0000000000:8eb6:94dd:e53f:0007:600:8000 ->:: 8 eb6: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:83517469:100f: 8006:900d: e53f: cfe7:61a9:8351 ->7469:100f: 8006:900d: e53f: cfe7:61a9:83517000:1200:8e00:94dd: e53f: cfe7:0000:0001 ->7000:1200:8e00:94dd: e53f: cfe7:0:100000000000000000000000000000000000000000000000 ->::0:0:0:94dd: 0:0:0:94dd::0:1200:: 0:1200::00000000000000:1200: 00000000000000:8351 ->::1200:0:0:0:83510000: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:619 a9: 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 0:005f: 0:94dd:0000: cfe7:0:8351 -> 0:5f:0:94dd:0:cfe7:0:8351000:000f: 000:94dd:0000:cfe7: 000:8351 -> 0:f:0:94dd:0:cfe7:0:83510000:0000:0000:0000:0000:0000:0000:0001 ->:: 1

在执行一些测试后,我认为以下捕获了所有不同的IPv6场景:

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

最新更新