Проверьте, является ли String шестнадцатеричным

У меня есть строка типа "09a", и мне нужен метод, чтобы подтвердить, является ли текст шестнадцатеричным. Код, который я опубликовал, делает нечто похожее, он проверяет, что строка является десятичным числом. Я хочу сделать то же самое, но для шестнадцатеричного.

    private static boolean isNumeric(String cadena) {
    try {
        Long.parseLong(cadena);
        return true;
    } catch (NumberFormatException nfe) {
        JOptionPane.showMessageDialog(null,"Uno de los números, excede su capacidad.");
        return false;
    }
}

Ответ 1

Там перегружен Long.parseLong, который принимает второй параметр, указав радиус:

Long.parseLong(cadena,16);

В качестве альтернативы вы можете перебирать символы в строке и вызывать Character.digit(c,16) (если какой-либо из них возвращает -1 это не допустимая шестнадцатеричная цифра). Это особенно полезно, если строка слишком велика, чтобы она помещалась в long (как указано в комментариях, что вызовет исключение, если используется первый метод). Пример:

private static boolean isNumeric(String cadena) {
    if ( cadena.length() == 0 || 
         (cadena.charAt(0) != '-' && Character.digit(cadena.charAt(0), 16) == -1))
        return false;
    if ( cadena.length() == 1 && cadena.charAt(0) == '-' )
        return false;

    for ( int i = 1 ; i < cadena.length() ; i++ )
        if ( Character.digit(cadena.charAt(i), 16) == -1 )
            return false;
    return true;
}

Кстати, я бы предложил отделить проблемы "тестирование на допустимое число" и "отображение сообщения пользователю", поэтому я просто вернул false в приведенном выше примере вместо того, чтобы сначала уведомить пользователя.

Наконец, вы можете просто использовать регулярное выражение:

cadena.matches("-?[0-9a-fA-F]+");

Ответ 2

Ужасное злоупотребление исключениями. Никогда не делай этого! (Это не я, это Josh Bloch Effective Java). Во всяком случае, я предлагаю

private static final Pattern HEXADECIMAL_PATTERN = compile("\\p{XDigit}+");

private boolean isHexadecimal(String input) {
    Matcher matcher = HEXADECIMAL_PATTERN.matcher(input);
    return matcher.matches();
}

Ответ 3

Используется в моем собственном коде, чтобы проверить, является ли строка MAC-адресом

boolean isHex = mac_addr.matches("^[0-9a-fA-F]+$");

Моя говядина с другими ответами, представленными в этом потоке, состоит в том, что если длина строки велика, она также генерирует исключение. Поэтому не очень полезно, если вы тестируете, если MAC-адрес состоит из действительных шестнадцатеричных символов.

Не бойтесь использовать регулярное выражение!

Ответ 4

Long.parseLong имеет вторую форму, которая принимает в качестве второго аргумента значение radix.

private static boolean isHexNumber (String cadena) {
  try {
    Long.parseLong(cadena, 16);
    return true;
  }
  catch (NumberFormatException ex) {
    // Error handling code...
    return false;
  }
}

Ответ 5

Здесь приведен код для разных параметров и времени выполнения (JDK 8):

execution time isHex1: 4540
execution time isHex2: 420
execution time isHex3: 7907
execution time regex: 46827

Тестовый код:

@Test
public void testPerformance() {
    int count = 100000000;
    char[] chars = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f',
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
    };
    String regexString = new String(chars);
    Pattern pattern = Pattern.compile("^[0-9a-fA-F]+$");
    long start = System.currentTimeMillis();
    for (int i = 0; i < count; i++) {
        for (char c: chars) {
            isHex1(c);
        }
    }
    System.out.println("execution time isHex1: " + (System.currentTimeMillis() - start));
    start = System.currentTimeMillis();
    for (int i = 0; i < count; i++) {
        for (char c: chars) {
            isHex2(c);
        }
    }
    System.out.println("execution time isHex2: " + (System.currentTimeMillis() - start));
    for (int i = 0; i < count; i++) {
        for (char c: chars) {
            isHex3(c);
        }
    }
    System.out.println("execution time isHex3: " + (System.currentTimeMillis() - start));
    for (int i = 0; i < count; i++) {
        Matcher matcher = pattern.matcher(regexString);
        matcher.matches();
    }
    System.out.println("execution time regex: " + (System.currentTimeMillis() - start));
}

private boolean isHex1(char c) {
    return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
}

private boolean isHex2(char c) {
    switch (c) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
        case 'a':
        case 'b':
        case 'c':
        case 'd':
        case 'e':
        case 'f':
        case 'A':
        case 'B':
        case 'C':
        case 'D':
        case 'E':
        case 'F':
            return true;
        default:
            return false;
    }
}

private boolean isHex3(char c) {
    return (Character.digit(c, 16) != -1);
}

Ответ 6

Без-библиотечный подход

public static boolean isHexadecimal(String value)
{
    if (value.startsWith("-"))
    {
        value = value.substring(1);
    }

    value = value.toLowerCase();

    if (value.length() <= 2 || !value.startsWith("0x"))
    {
        return false;
    }

    for (int i = 2; i < value.length(); i++)
    {
        char c = value.charAt(i);

        if (!(c >= '0' && c <= '9' || c >= 'a' && c <= 'f'))
        {
            return false;
        }
    }

    return true;
}

Ответ 7

Вы можете проверить текст любой длины с помощью метода ниже.

public static boolean isHexadecimal(String text) {
    Objects.requireNonNull(text);
    if(text.length() < 1)
        throw new IllegalArgumentException("Text cannot be empty.");

    char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'a', 'b', 'c', 'd', 'e', 'f', 'A', 'B', 'C', 'D', 'E', 'F' };

    for (char symbol : text.toCharArray()) {
        boolean found = false;
        for (char hexDigit : hexDigits) {
            if (symbol == hexDigit) {
                found = true;
                break;
            }
        }
        if(!found)
            return false;
    }
    return true;
}