验证String是否为十六进制

Axe*_*uez 14 java string hex

我有一个类似"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;
    }
}
Run Code Online (Sandbox Code Playgroud)

mgi*_*nbr 22

有一个重载Long.parseLong,接受第二个参数,指定基数:

Long.parseLong(cadena,16);
Run Code Online (Sandbox Code Playgroud)

作为替代方案,您可以迭代字符串中的字符并调用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;
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,我建议将"测试有效数字"和"向用户显示消息"的问题分开,这就是为什么我只是false在上面的例子中返回而不是先通知用户.

最后,您可以简单地使用正则表达式:

cadena.matches("-?[0-9a-fA-F]+");
Run Code Online (Sandbox Code Playgroud)


Evg*_*eev 17

可怕的滥用例外情况.不要这样做!(这不是我,这是Josh Bloch的有效Java).无论如何,我建议

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

private boolean isHexadecimal(String input) {
    final Matcher matcher = HEXADECIMAL_PATTERN.matcher(input);
    return matcher.matches();
}
Run Code Online (Sandbox Code Playgroud)

  • 现在(从我的基准测试中)使用正则表达式比使用`parseLong`慢一点,假设绝大多数字符串实际上是正确的.我实际上同意使用异常可能并不完美,并且有更好的解决方案,我对你的答案的主要反对意见是你建议的东西比使用异常更糟糕. (3认同)
  • 你错误地引用了 Effective Java,应该避免异常来控制逻辑流。如果不正确的十六进制字符串确实是一个异常事件,那么没有理由不使用 `parseLong` 并捕获异常。Josh 的书给出了一个总是抛出异常来控制循环的例子,这不是真的。此外,Josh 的关注点还与效率和可读性有关,但您建议使用 REGEX,它既慢又不可读。 (2认同)

lay*_*cat 14

在我自己的代码中使用它来检查字符串是否是MAC地址

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

我对此线程中提供的其他答案的看法是,如果String的长度很大,它也会抛出异常.因此,如果您正在测试MAC地址是否包含有效的十六进制数,则不是非常有用.

不要害怕使用正则表达式!

  • 每次检查时都会编译正则表达式,通常最好使用Pattern。 (3认同)

Ton*_*ony 9

Long.parseLong有第二种形式,它将基数作为第二个参数.

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


too*_*ges 5

以下是用于不同选项和执行时间结果的代码(JDK 8):

execution time isHex1: 4540
execution time isHex2: 420
execution time isHex3: 7907
execution time regex: 46827
Run Code Online (Sandbox Code Playgroud)

测试代码:

@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);
}
Run Code Online (Sandbox Code Playgroud)