我想知道是否有一个库可以用来将长 IPv6 地址(例如 2002:9876:57AB:0000:0000:0000:0000:0001)的表示形式转换为压缩的 IPv6 形式(在本例中:2002:9876:57AB::1).
我找不到这样的图书馆。该库不应使用任何 IP Api,不得建立网络连接。
我已经尝试过了
return Inet6Address.getByName(longAdress).toString();
但这只是将 4 个零替换为 1 个零(在本例中为 2002:9876:57AB:0:0:0:0:1)。
有什么建议吗?
java-ipv6 是一个非常不错的库。它还可以很好地处理地址范围。
public class Ipv6AddressCompressor {
public static String getCompressedAddress(String longAddress) throws UnknownHostException {
longAddress = Inet6Address.getByName(longAddress).getHostAddress();
return longAddress.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
}
}
这应该可以保护您免受无效地址的影响(抛出 UnknownHostException),并将正确压缩尾随 ipv4 地址(即 0:0:0:0:0:0:255.255.255.255 -> ::FFFF:FFFF)。这也将防止已经压缩的地址。
开源IPAddress Java库可以进行IP地址解析并生成各种字符串。免责声明:我是该图书馆的项目经理。
示例代码:
String ipv6 = "2002:9876:57AB:0000:0000:0000:0000:0001";
try {
IPAddressString str = new IPAddressString(ipv6);
IPAddress addr = str.toAddress();
String compressed = addr.toCompressedString();
System.out.println(compressed); //
} catch(IPAddressStringException e) {
//e.getMessage has validation error
}
输出:
2002:9876:57ab::1
你可以试试这个代码。它可能会比正则表达式的等效项表现得更好(不是我对它进行了基准测试,或者其他什么)。它也经过了很好的测试。
请注意,您需要使用 IP 地址的数字表示形式(在
byte[]
中)。要获得它,如果您需要解析主机名,可以执行 InetAddress.getByName(ip).getAddress()
,或者使用 sun 实用程序类 IPAddressUtil.textToNumericFormatV6(ip)
从 IP 地址进行解析,无需主机解析。
private static final char[] ipv6conseqZeroFiller = { ':', ':' };
private static final char ipv6hextetSeparator = ':';
/*
* Convert numeric IPv6 to compressed format, where
* the longest sequence of 0's (with 2 or more 0's) is replaced with "::"
*/
public static String ipv6toCompressedForm(byte[] src) {
assert src.length == 16;
//Find the longest sequence of 0's
int cmprHextet = -1; //start of compressed region (hextet index)
int cmprSize = 0; //length of compressed region
for (int hextet = 0; hextet < 8;) {
int curByte = hextet * 2;
int size = 0;
while (curByte < src.length && src[curByte] == 0
&& src[curByte + 1] == 0) {
curByte += 2;
size++;
}
if (size > cmprSize) {
cmprHextet = hextet;
cmprSize = size;
}
hextet = (curByte / 2) + 1;
}
if (cmprHextet == -1 || cmprSize < 2) {
//No compression can be applied
return ipv6toStr(src);
}
StringBuilder sb = new StringBuilder(39);
ipv6toStr(sb, src, 0, cmprHextet);
sb.append(ipv6conseqZeroFiller);
ipv6toStr(sb, src, cmprHextet + cmprSize, 8);
return sb.toString();
}
/*
* Convert numeric IPv6 to standard (non-compressed) format.
*
* Borrowed from Inet6Address.java #numericToTextFormat(byte[])
* Changed StringBuffer -> StringBuilder and ":" -> ':' for performance.
*/
public static String ipv6toStr(byte[] src) {
assert src.length == 16;
StringBuilder sb = new StringBuilder(39);
ipv6toStr(sb, src, 0, 8);
return sb.toString();
}
private static final void ipv6toStr(StringBuilder sb, byte[] src,
int fromHextet, int toHextet) {
for (int i = fromHextet; i < toHextet; i++) {
sb.append(Integer.toHexString(((src[i << 1] << 8) & 0xff00)
| (src[(i << 1) + 1] & 0xff)));
if (i < toHextet - 1) {
sb.append(ipv6hextetSeparator);
}
}
}
import com.google.common.net.InetAddresses;
// Convert the short IPv6 address to a full version
InetAddress inetAddress = InetAddresses.forString(shortIPv6);
return inetAddress.getHostAddress();