Java中IPV6地址转换成压缩形式

发布于 2024-11-29 10:57:38 字数 1360 浏览 0 评论 0原文

我使用 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. < a href="https://www.rfc-editor.org/rfc/rfc5952#section-4.2.1" rel="nofollow noreferrer">尽可能缩短:例如,2001:db8:0:0:0:0:2:1 必须缩短为
    2001:db8::2:1。同样,2001:db8::0:1 也是不可接受的, 因为符号“::”可以用来产生 较短的表示形式 2001:db8::1。

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

  3. 选择“::”的位置 : = 当“::”的位置有替代选择时, 连续 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 是正确的 代表。

我还检查了另一个发布在堆栈溢出中,但没有指定条件(例如选择 :: 的位置)。

有没有java库可以处理这个问题?有人可以帮我吗?

提前致谢。

I have used Inet6Address.getByName("2001:db8:0:0:0:0:2:1").toString() method to compress IPv6 address, and the output is 2001:db8:0:0:0:0:2:1 ,but i need 2001:db8::2:1 . , Basically the compression output should based on RFC 5952 standard , that is

  1. Shorten as Much as Possible : For example, 2001:db8:0:0:0:0:2:1 must be shortened to
    2001:db8::2:1.Likewise, 2001:db8::0:1 is not acceptable,
    because the symbol "::" could have been used to produce a
    shorter representation 2001:db8::1.

  2. Handling One 16-Bit 0 Field : The symbol "::" MUST NOT be used to shorten just one 16-bit 0 field.
    For example, the representation 2001:db8:0:1:1:1:1:1 is correct, but
    2001:db8::1:1:1:1:1 is not correct.

  3. Choice in Placement of "::" : = When there is an alternative choice in the placement of a "::", the
    longest run of consecutive 16-bit 0 fields MUST be shortened (i.e.,
    the sequence with three consecutive zero fields is shortened in 2001:
    0:0:1:0:0:0:1). When the length of the consecutive 16-bit 0 fields
    are equal (i.e., 2001:db8:0:0:1:0:0:1), the first sequence of zero
    bits MUST be shortened. For example, 2001:db8::1:0:0:1 is correct
    representation.

I have also checked another post in Stack overflow, but there was no condition specified (example choice in placement of ::).

Is there any java library to handle this? Could anyone please help me?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

猫瑾少女 2024-12-06 10:57:38

这个怎么样?

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 结尾,是否还有其他规则?)

How about this?

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

Explanation without Java double-backslash hell:

(       # 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.

Input:

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

Output:

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::

(I hope the last example is correct - or is there another rule if the address ends in 0?)

他是夢罘是命 2024-12-06 10:57:38

我最近遇到了同样的问题,并且想(非常轻微地)改进蒂姆的答案。

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

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

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

I recently ran into the same problem and would like to (very slightly) improve on Tim's answer.

The following regular expression offers two advantages:

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

Firstly, it incorporates the change to match multiple zeroes. Secondly, it also correctly matches addresses where the longest chain of zeroes is at the beginning of the address (such as 0:0:0:0:0:0:0:1).

朦胧时间 2024-12-06 10:57:38

Guava 的 InetAddresses 类具有 toAddrString() 其格式根据 RFC 5952。

Guava's InetAddresses class has toAddrString() which formats according to RFC 5952.

我们只是彼此的过ke 2024-12-06 10:57:38

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

java-ipv6 is almost what you want. As of version 0.10 it does not check for the longest run of zeroes to shorten with :: - for instance 0:0:1:: is shortened to ::1:0:0:0:0:0. It is a very decent library for the handling of IPv6 addresses, though, and this problem should be fixed with version 0.11, such that the library is RFC 5952 compliant.

淡墨 2024-12-06 10:57:38

开源 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

The open-source IPAddress Java library can do as described, it provides numerous ways of producing strings for IPv4 and/or IPv6, including the canonical string which for IPv6 matches rfc 5952. Disclaimer: I am the project manager of that library.

Using the examples you list, sample code is:

    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
在风中等你 2024-12-06 10:57:38

不太优雅,但这是我的建议(基于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

Not quite elegant but this is my proposal (based on chrixm work):

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. results:

    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

一花一树开 2024-12-06 10:57:38

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

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

After performing some tests, I think the following captures all the different IPv6 scenarios:

"((?:(?::0|0:0?)\\b){2,}):?(?!\\S*\\b\\1:0\\b)(\\S*)" -> "::$2"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文