Подтвердить что ты не робот

Проверка строки IPv4 в Java

Метод Bellow проверяет правильность строки в правиле IPv4-адреса, если он действителен. Любые улучшения в регулярном выражении и элегантности будут очень оценены:

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;
    }
}
4b9b3361

Ответ 1

Вот более легкий для чтения, немного менее эффективный способ, которым вы могли бы это сделать.

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

Ответ 2

UPDATE: Commons-HttpClient и его преемник HttpComponents-HttpClient используют эту функцию. Вы можете использовать эту версию так: InetAddressUtils.isIPv4Address(Str).


Версия разработки Apache Commons Validator имеет InetAddressValidator, который имеет метод isValidInet4Address(String), чтобы выполнить проверку, чтобы убедиться, что данный String является допустимым адресом IPv4.

Исходный код можно просмотреть из репозитория, так что это может дать некоторые идеи для улучшения, если вы чувствуете, что есть.

Быстрый взгляд на предоставленный код показывает, что ваш метод компилирует Pattern для каждого вызова метода. Я переместил бы этот класс Pattern в поле static, чтобы избежать дорогостоящего процесса компиляции шаблона при каждом вызове.

Ответ 3

Если вы хотите использовать библиотеку с выпущенной версией, поддерживающую поддержку IPv4 и IPv6, вы можете использовать Guava

boolean isValid = InetAddresses.isInetAddress("1.2.3.4");

Ответ 4

Здесь решение, которое использует потоки Java 8, чтобы проверить, что адрес состоит из ровно 4 чисел от 0 до 255 включительно, разделенных точками:

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]
    }
}

Ответ 5

Если вы не против использования разрешения dns на недействительных ip-адресах, таких как www.example.com, вы можете использовать методы InetAddress для проверьте:

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

Метод проверяет, является ли это экземпляром Inet4Address, и если параметр был ip-адресом, а не именем хоста. Если вы ожидаете большого количества имен хостов в качестве параметров, будьте осторожны, чтобы эта реализация использовала DNS, чтобы попытаться ее решить. Это может быть проблемой производительности.

В противном случае вы можете иметь пик в boolean sun.net.util.IPAddressUtil.isIPv4LiteralAddress(String src) как синтаксический анализ строки для проверки IPv4.

Ответ 6

Найдите пример регулярного выражения из 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();             
    }
}

Ответ 7

Вдумайтесь, что это решение довольно изящно, хотя для его понимания требуется минута.

Основная идея - взять подстроку и подтвердить ее.
Обратите внимание, что я переключаю x и y, так как начало подстроки всегда будет концом последнего плюс 1.

Это решение примерно в 20 раз быстрее, чем вариант с регулярным выражением, и в 2 раза быстрее, чем разделение.

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

Если вы знаете, что у вас будет много неправильных IP-адресов, подумайте над добавлением следующего кода ниже первого, если. Это сделает код 1,5x медленнее, но в случае ошибки улучшите его на 700x

    for (int i = 0; i < ip.length(); i++) {
        if (!Character.isDigit(ip.charAt(i)) && ip.charAt(i) != '.') return false;
    }

Ответ 8

Если вы используете код в вопросе, вы хотите изменить строку:

if ((ip.length() < 6) & (ip.length() > 15)) return false;

to

if ((ip.length() <= 6) || (ip.length() > 15)) return false;

Ответ 9

Попробуйте использовать следующий regrex для 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}$";

надеюсь, что это поможет:)

Ответ 10

Я думаю, что правильным способом является создание класса IPAddress и его инициализация путем предоставления ему строкового представления IP-адреса.

Таким образом вы можете разделить различные этапы проверки в методах экземпляра и получить разделение беспокойства.

Например, это обычно это собственный метод, назовите это просто isEmpty:

return (ip == null || ip.isEmpty());

Также это должен быть отдельный метод, вы можете назвать это hasProbableLength.

ip = ip.trim();
return ((ip.length() < 6) & (ip.length() > 15));

Здесь много чего происходит. Я попытался бы разбить это и, возможно, попытаюсь полностью пропустить регулярное выражение.

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

Сначала я разделил строку на точки и увидел, что получаю ровно четыре группы. Вызовите этот метод divideIntoGroups

Затем я проверил бы каждую из групп на значение от 0 до 255. Вызовите этот метод validateGroups

Теперь, когда у вас есть это, если вы когда-либо захотите расширить этот класс, чтобы также искать, является ли IP-адрес локальным хостом или является широковещательным адресом, это довольно легко сделать. Это то, что дает разделение проблем.

Вы также можете точно указать, какое из ваших правил проверки было нарушено при проверке строки IP-адреса. Что-то, что регулярное выражение не будет.

Ответ 11

Самый простой способ, который я нашел, чтобы проверить данный ip правильно в ipv4, - использовать commons-validator-1.4.0.jar, имеет класс: -

org.apache.commons.validator.routines.InetAddressValidator

InetAddressValidator

например.

InetAddressValidator inetValidator = InetAddressValidator.getInstance();
inetValidator.isValidInet4Address(yourIPAddress);

который использует это простое регулярное выражение: -

  "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$";

Ответ 12

Большинство ответов (за исключением Майкла Коницки) ошибочны: например, 10.8 является допустимым адресом IP4 (сокращенное значение для 10.0.0.8).

См. Текстовое представление IP-адресов в спецификациях Java.

Как можно видеть в ссылке, чтобы проверить числовое представление, может быть от 1 до 4 частей, и в каждом случае применяются различные ограничения на части.

Ответ 13

Я бы предложил использовать то, что доступно на платформе/структуре, которую вы разрабатываете.

Если вы ничего не считаете достаточно хорошим, вы можете просто добавить скомпилированное регулярное выражение в класс-помощник. Например, здесь, как это делает платформа Android:

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]))");

Ответ 14

boolean isValid = inetAddressValidator.isValid(hostName) || hostName.equalsIgnoreCase("localhost");

тот же ответ, что и coobird. Просто добавьте localhost в оператор. Большинство сред принимает "localhost" как допустимое имя хоста. Это не формат ipv4, но он должен быть включен для рассмотрения действительности.

Ответ 15

Библиотека Java IPAddress будет делать это. Javadoc доступен по ссылке. Отказ от ответственности: я руководитель проекта.

Эта библиотека поддерживает прозрачность IPv4 и IPv6, поэтому проверка выполняется либо так же, как и ниже, а также поддерживает также адреса IPC4 с префиксом длины CIDR. Он поддерживает более необычные форматы, такие как inet_aton (например, 10.8 упоминался здесь в другом ответе)

Убедитесь, что адрес действителен:

    String str = "1.2.3.4";
    IPAddressString addrString = new IPAddressString(str);
    try {
         IPAddress addr = addrString.toAddress();
         ...
    } catch(AddressStringException e) {
        //e.getMessage provides validation issue
    }

Ответ 16

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