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-библиотека для обработки этого? Может ли кто-нибудь помочь мне?
Спасибо заранее.
Ответы
Ответ 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;
}
Результаты:
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