Подтвердить что ты не робот

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 standard, то есть

1) Сократить как можно больше: Например, 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-библиотека для обработки этого? Может ли кто-нибудь помочь мне?

Спасибо заранее.

4b9b3361

Ответ 1

Как насчет этого?

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

Объяснение без 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.

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

Вывод:

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?)

Ответ 2

Недавно я столкнулся с той же проблемой и хотел бы (очень немного) улучшить ответ Тима.

Следующее регулярное выражение предлагает два преимущества:

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

Во-первых, он включает изменение в соответствии с несколькими нулями. Во-вторых, он также правильно соответствует адресам, где самая длинная цепочка нулей находится в начале адреса (например, 0:0:0:0:0:0:0:1).

Ответ 3

java-ipv6 - это почти то, что вы хотите. Начиная с версии 0.10 он не проверяет, чтобы самый длинный пробег нулей сокращался с:: - например, 0: 0: 1:: сокращен до:: 1: 0: 0: 0: 0: 0. Это очень приличная библиотека для обработки адресов IPv6, и эта проблема должна быть исправлена ​​с версией 0.11, так что библиотека совместимый с RFC 5952.

Ответ 4

В классе Guava InetAddresses toAddrString(), который форматирует в соответствии с RFC 5952.

Ответ 5

После выполнения некоторых тестов, я думаю, что следующие захватывают все различные сценарии IPv6:

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

Ответ 6

Java-библиотека с открытым исходным кодом IPAddress может делать, как описано, она предоставляет множество способов создания строк для 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: 94дд: e53f: 7: 6009: 8350 0000: 0000: 8eb6: 94dd: e53f: 0007: 6009: 8300 -> :: 8eb6: 94дд: e53f: 7: 6009: 8300 0000: 0000: 8eb6: 94dd: e53f: 0007: 6009: 8000 -> :: 8eb6: 94дд: 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: 94дд: 0000: 0000: 0000: 0000 → 0: 0: 0: 94дд :: 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: 94дд: 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