2010-09-21 6 views
5

Je voudrais savoir s'il existe une bibliothèque que je peux utiliser pour convertir une représentation d'une adresse IPv6 longue (comme 2002: 9876: 57AB: 0000: 0000: 0000: 0000: 0001) dans le formulaire IPv6 compressé (dans ce cas: 2002: 9876: 57AB :: 1).Java Library pour convertir une adresse IPv6 longue en sa forme compressée

Je n'ai pas réussi à trouver une telle bibliothèque. Cette bibliothèque ne doit pas utiliser d'API IP, une connexion réseau ne doit pas être établie.

Je l'ai déjà essayé

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

mais cela remplace juste les 4 zéros avec 1 zéro (dans ce cas 2002: 9876: 57AB: 0: 0: 0: 0: 1).

des suggestions?

+0

Voir aussi http://stackoverflow.com/q/7043983/21499 –

Répondre

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

Cela devrait vous protéger contre les adresses invalides (jette le UnknownHostException), et correctement la compression arrière adresses ipv4 (c.-à-0: 0: 0: 0: 0: 0: 255.255.255.255 -> :: FFFF: FFFF). Cela protégera également contre les adresses déjà compressées.

+2

Sauf qu'il ne supprime pas les zéros redondants, par exemple, ' 0000: 0000: 0001' devrait être ':: 1' mais devient' :: 0001' - réparable en faisant quelque chose comme 'replaceAll (" (: | ^) 0 + (\\ d) "," $ 1 $ 2 ")' sur le résultat, cependant. – gustafc

+0

Bonne prise. Votre \\ d devrait être [0-9A-Fa-F] cependant. Mettra à jour pour corriger. –

+0

Attention: Inet6Address.getByName peut mener à des requêtes DNS si vous alimentez par exemple. une adresse brisée comme ":: 1 ::" dedans. Cela peut prendre quelques secondes sur un seul appel! –

0

Vous pouvez essayer ce code. Il va probablement mieux performer que l'équivalent regex (pas que je l'ai référencé, ou quoi que ce soit). C'est assez bien testé aussi.

Notez que vous devrez utiliser une représentation numérique (au byte[]) de l'adresse IP. Pour l'obtenir, vous pouvez soit faire InetAddress.getByName(ip).getAddress() si vous avez besoin de résoudre les noms d'hôtes, ou utiliser la classe d'utilité solaire IPAddressUtil.textToNumericFormatV6(ip) pour analyser à partir d'une adresse IP sans résolution de l'hôte.

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

java-ipv6 est une bibliothèque très décente pour cela. Il gère également les plages d'adresses.

1

The open-source IPAddress Java library peut faire l'analyse d'adresse IP et produire une variété de chaînes. Disclaimer: Je suis le chef de projet de cette bibliothèque.

code Exemple:

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 
    } 

sortie:

2002:9876:57ab::1