Убедитесь, что строка является шестнадцатеричной
У меня есть строка типа "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;
}
}
8 ответов
Ужасное злоупотребление исключениями. Никогда не делай этого! (Это не я, это Эффективная Ява Джоша Блоха). Во всяком случае, я предлагаю
boolean isNumeric = str.matches("\\p{XDigit}+");
Там перегружен 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]+");
Использовал это в своем коде, чтобы проверить, является ли строка MAC-адресом.
boolean isHex = mac_addr.matches("^[0-9a-fA-F]+$");
Моя претензия к другим ответам, представленным в этой теме, заключается в том, что, если длина строки велика, она также выдаст исключение. Поэтому не очень полезно, если вы проверяете, состоит ли MAC-адрес из действительных шестнадцатеричных значений.
Не пугайтесь использования регулярных выражений!
Вот некоторый код для различных опций и результатов времени выполнения (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);
}
Long.parseLong имеет вторую форму, которая принимает основание в качестве второго аргумента.
private static boolean isHexNumber (String cadena) {
try {
Long.parseLong(cadena, 16);
return true;
}
catch (NumberFormatException ex) {
// Error handling code...
return false;
}
}
Безбиблиотечный подход
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;
}
Попробуй это.
static boolean isHexadecimal(String s) {
return s.chars()
.skip(s.startsWith("-") ? 1 : 0)
.allMatch(c -> "0123456789ABCDEFabcdef".indexOf(c) >= 0);
}
public static void main(String[] args) {
System.out.println(isHexadecimal("-0e34a29Fb"));
System.out.println(isHexadecimal("-ff-"));
System.out.println(isHexadecimal("ef-"));
System.out.println(isHexadecimal("efg"));
}
выход:
true
false
false
false
Вы можете опустить
.skip(s.startsWith("-") ? 1 : 0)
если вы не позволите знак.
Вы можете проверить любой длины текста с помощью метода ниже практически.
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;
}