开发者

Java Library for converting a long IPv6 address into its compressed form

开发者 https://www.devze.com 2023-01-17 04:24 出处:网络
I would like to know, whether there is a library which I can use to convert a represenation of a long IPv6 address (such as 2002:9876:57AB:0000:0000:0000:0000:0001) into the compressed IPv6 form (in t

I would like to know, whether there is a library which I can use to convert a represenation of a long IPv6 address (such as 2002:9876:57AB:0000:0000:0000:0000:0001) into the compressed IPv6 form (in this case: 2002:9876:57AB::1).

I was not able t开发者_运维百科o find such a library. This library should not use any IP Api, a network connection must not be made.

I already tried

return Inet6Address.getByName(longAdress).toString();

but this just replaces the 4 zeros with 1 zero (in this case 2002:9876:57AB:0:0:0:0:1).

any suggestions?


java-ipv6 is a very decent library for that. It also handles address ranges well.


public class Ipv6AddressCompressor {
    public static String getCompressedAddress(String longAddress) throws UnknownHostException {
        longAddress = Inet6Address.getByName(longAddress).getHostAddress();
        return longAddress.replaceFirst("(^|:)(0+(:|$)){2,8}", "::");
    }
}

This should protect you against invalid addresses (throws the UnknownHostException), and will properly compress trailing ipv4 addresses (i.e. 0:0:0:0:0:0:255.255.255.255 -> ::FFFF:FFFF). This will also protect against already compressed addresses.


The open-source IPAddress Java library can do ip address parsing and produce a variety of strings. Disclaimer: I am the project manager of that library.

Example code:

    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
    }

output:

2002:9876:57ab::1


You can try this code. It'll probably perform better than the regex equivalent (not that I have benchmarked it, or anything). It's pretty well tested too.

Note that you will need to use a numeric representation (in byte[]) of the IP address. To get it you can either do InetAddress.getByName(ip).getAddress() if you need to resolve host names, or use sun utility class IPAddressUtil.textToNumericFormatV6(ip) to parse from an IP address without host resolution.

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);
        }
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号