La méthode ci-dessous valide si chaîne est correcte. L'adresse IPv4 renvoie true si elle est valide. Toute amélioration de l'expression rationnelle et de l'élégance serait très appréciée:
public static boolean validIP(String ip) {
if (ip == null || ip.isEmpty()) return false;
ip = ip.trim();
if ((ip.length() < 6) & (ip.length() > 15)) return false;
try {
Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
Matcher matcher = pattern.matcher(ip);
return matcher.matches();
} catch (PatternSyntaxException ex) {
return false;
}
}
Voici un moyen plus facile à lire, légèrement moins efficace.
public static boolean validIP (String ip) {
try {
if ( ip == null || ip.isEmpty() ) {
return false;
}
String[] parts = ip.split( "\\." );
if ( parts.length != 4 ) {
return false;
}
for ( String s : parts ) {
int i = Integer.parseInt( s );
if ( (i < 0) || (i > 255) ) {
return false;
}
}
if ( ip.endsWith(".") ) {
return false;
}
return true;
} catch (NumberFormatException nfe) {
return false;
}
}
UPDATE: Commons-HttpClient et son successeur HttpComponents-HttpClient ont adopté cette fonctionnalité. Vous pouvez utiliser cette version comme ceci: InetAddressUtils.isIPv4Address(Str)
.
La version de développement de Apache Commons Validator a une classe InetAddressValidator
qui possède une méthode isValidInet4Address(String)
afin de vérifier si une String
donnée est une adresse IPv4 valide.
Le code source peut être visualisé à partir du référentiel, ce qui pourrait vous donner des idées d’améliorations, le cas échéant.
Un rapide coup d'œil sur le code fourni montre que votre méthode compile une variable Pattern
à chaque appel de la méthode. Je déplacerais cette classe Pattern
dans un champ static
afin d'éviter le processus coûteux de compilation de modèles à chaque appel.
Si vous souhaitez utiliser une bibliothèque avec une version publiée prenant en charge les supports IPv4 et IPv6, vous pouvez utiliser Guava
boolean isValid = InetAddresses.isInetAddress("1.2.3.4");
Voici une solution qui utilise des flux Java 8 pour vérifier que l’adresse est composée de 4 chiffres compris entre 0 et 255 inclus, séparés par des points:
public class IpValidation {
/**
* Check that a string represents a decimal number
* @param string The string to check
* @return true if string consists of only numbers without leading zeroes, false otherwise
*/
public static boolean isDecimal(String string) {
if (string.startsWith("0")) {
if (string.length() == 1) {
// "0"
return true;
}
// The string has a leading zero but is not "0"
return false;
}
for(char c : string.toCharArray()) {
if(c < '0' || c > '9') {
return false;
}
}
return true;
}
public static boolean isIp(String string) {
String[] parts = string.split("\\.", -1);
return parts.length == 4 // 4 parts
&& Arrays.stream(parts)
.filter(IpValidation::isDecimal) // Only decimal numbers
.map(Integer::parseInt)
.filter(i -> i <= 255 && i >= 0) // Must be inside [0, 255]
.count() == 4; // 4 numerical parts inside [0, 255]
}
}
Si cela ne vous dérange pas d'utiliser la résolution DNS sur des adresses IP invalides comme www.example.com
, vous pouvez utiliser les méthodes InetAddress pour vérifier
public static final boolean checkIPv4(final String ip) {
boolean isIPv4;
try {
final InetAddress inet = InetAddress.getByName(ip);
isIPv4 = inet.getHostAddress().equals(ip)
&& inet instanceof Inet4Address;
} catch (final UnknownHostException e) {
isIPv4 = false;
}
return isIPv4;
}
La méthode vérifie s'il s'agit d'une instance d'Inet4Address et si le paramètre correspond à l'adresse IP et non au nom d'hôte. Si vous attendez beaucoup de noms d’hôte en tant que paramètres, sachez que cette implémentation utilise DNS pour tenter de le résoudre. Cela pourrait être un problème de performance.
Sinon, vous pouvez avoir un pic dans boolean Sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String src)
comment la chaîne est analysée pour IPv4-check.
Trouvez un exemple de regex dans this
package com.mkyong.regex;
import Java.util.regex.Matcher;
import Java.util.regex.Pattern;
public class IPAddressValidator{
private Pattern pattern;
private Matcher matcher;
private static final String IPADDRESS_PATTERN =
"^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +
"([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
public IPAddressValidator(){
pattern = Pattern.compile(IPADDRESS_PATTERN);
}
/**
* Validate ip address with regular expression
* @param ip ip address for validation
* @return true valid ip address, false invalid ip address
*/
public boolean validate(final String ip){
matcher = pattern.matcher(ip);
return matcher.matches();
}
}
Je pense que cette solution est assez élégante, même si cela prend une minute pour la comprendre.
L'idée de base est de prendre une sous-chaîne et de la valider.
Veuillez noter que je change x et y, car le début d'une sous-chaîne sera toujours la fin de la dernière plus 1.
Cette solution est environ 20 fois plus rapide qu’une variante regex et deux fois plus rapide que le fractionnement.
public static boolean validIP(String ip) {
if(ip == null || ip.length() < 7 || ip.length() > 15) return false;
try {
int x = 0;
int y = ip.indexOf('.');
if (y == -1 || ip.charAt(x) == '-' || Integer.parseInt(ip.substring(x, y)) > 255) return false;
x = ip.indexOf('.', ++y);
if (x == -1 || ip.charAt(y) == '-' || Integer.parseInt(ip.substring(y, x)) > 255) return false;
y = ip.indexOf('.', ++x);
return !(y == -1 ||
ip.charAt(x) == '-' ||
Integer.parseInt(ip.substring(x, y)) > 255 ||
ip.charAt(++y) == '-' ||
Integer.parseInt(ip.substring(y, ip.length())) > 255 ||
ip.charAt(ip.length()-1) == '.');
} catch (NumberFormatException e) {
return false;
}
}
Si vous savez que vous aurez beaucoup de mauvaises adresses IP, ajoutez le code suivant sous le premier if. Cela rendra le code 1,5x plus lent, mais en cas d'erreur, améliorez-le de 700x
for (int i = 0; i < ip.length(); i++) {
if (!Character.isDigit(ip.charAt(i)) && ip.charAt(i) != '.') return false;
}
Si vous utilisez le code dans la question, vous voudrez changer la ligne:
if ((ip.length() < 6) & (ip.length() > 15)) return false;
à
if ((ip.length() <= 6) || (ip.length() > 15)) return false;
La plupart des réponses (à l'exception de celle de Michael Konietzka) sont erronées: 10.8, par exemple, est une adresse IP4 valide (un raccourci pour 10.0.0.8).
Voir Représentation textuelle des adresses IP dans les spécifications Java.
Comme on peut le voir dans la référence, pour vérifier une représentation numérique, il peut y avoir 1 à 4 parties, et dans chaque cas, différentes limitations s'appliquent aux parties.
Essayez d’utiliser la regex suivante pour IPv4
String ip4Regex="^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$";
j'espère que ça aide :)
Je pense que le bon moyen est de construire une classe IPAddress
et de l'instancier en lui donnant une représentation sous forme de chaîne de l'adresse IP.
De cette façon, vous pouvez diviser les différentes étapes de validation en méthodes d'instance et obtenir une séparation séparation de préoccupations .
Par exemple, ceci est typiquement sa propre méthode, appelez simplement ceci isEmpty
:
return (ip == null || ip.isEmpty());
De plus, cela devrait être une méthode distincte, vous pouvez appeler celle-ci hasProbableLength
.
ip = ip.trim();
return ((ip.length() < 6) & (ip.length() > 15));
Ici, il se passe beaucoup de choses. Je voudrais essayer de casser cela et peut-être essayer de sauter la regex complètement.
try {
Pattern pattern = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
Matcher matcher = pattern.matcher(ip);
return matcher.matches();
} catch (PatternSyntaxException ex) {
return false;
}
Je voudrais d'abord diviser la chaîne en points et voir que je reçois exactement quatre groupes. Appelez cette méthode divideIntoGroups
Je validerais ensuite chacun des groupes pour une valeur comprise entre 0 et 255. Appelez cette méthode validateGroups
Maintenant que vous avez ceci, si vous souhaitez un jour étendre cette classe pour rechercher également si l'adresse IP est localhost ou s'il s'agit d'une adresse de diffusion, il est assez facile de le faire. C’est ce que vous donne la séparation des préoccupations .
Vous pouvez également savoir exactement laquelle de vos règles de validation a été rompue lors de la validation de la chaîne d'adresse IP. Quelque chose que regex ne sera pas.
Le moyen le plus simple que j'ai trouvé de vérifier si ip est correctement dans ipv4 consiste à utiliser commons-validator-1.4.0.jar a class
org.Apache.commons.validator.routines.InetAddressValidator
Par exemple.
InetAddressValidator inetValidator = InetAddressValidator.getInstance();
inetValidator.isValidInet4Address(yourIPAddress);
qui utilise cette regex simple: -
"^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";
boolean isValid = inetAddressValidator.isValid(hostName) || hostName.equalsIgnoreCase("localhost");
même réponse que coobird. Ajoutez simplement localhost à la déclaration. La plupart des environnements prennent "localhost" comme nom d'hôte valide. Ce n'est pas un format ipv4 mais il devrait être inclus pour que sa validité soit prise en compte.
La bibliothèque Java IPAddress le fera. Le javadoc est disponible sur le lien. Disclaimer: Je suis le chef de projet.
Cette bibliothèque prend en charge les protocoles IPv4 et IPv6 de manière transparente. Par conséquent, la validation de l'un ou de l'autre fonctionne de la même manière que ci-dessous et prend également en charge les adresses IPC4 de longueur préfixe CIDR. Il supporte les formats plus inhabituels comme inet_aton (par exemple 10.8 a été mentionné dans une autre réponse ici)
Vérifiez si une adresse est valide:
String str = "1.2.3.4";
IPAddressString addrString = new IPAddressString(str);
try {
IPAddress addr = addrString.toAddress();
...
} catch(AddressStringException e) {
//e.getMessage provides validation issue
}
public static boolean ipv4Check(String ipAddress){
try{
if(ipAddress!=null && !ipAddress.isEmpty()){
String [] ip = ipAddress.split("\\.");
if(ip.length!=4)
return false;
for(int i=0;i<=ip.length-1;i++){
int j=Integer.parseInt(ip[i]);
if(j<0 || j>255){
return false;
}
}
if ( ipAddress.endsWith(".") ) {
return false;
}
if ( ipAddress.startsWith(".") ) {
return false;
}
}
return true;
} catch (NumberFormatException ex) {
return false;
}
}
Je suggérerais d'utiliser ce qui est disponible sur la plate-forme/le cadre que vous développez.
Si rien n’est suffisant pour vous, vous voudrez peut-être simplement ajouter une expression rationnelle compilée à une classe d’aide. Par exemple, ici comment le framework Android le fait:
public static final Pattern IP_ADDRESS
= Pattern.compile(
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
+ "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ "|[1-9][0-9]|[0-9]))");