35

我有一个像“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;
    }
}
4

8 回答 8

34

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

Long.parseLong(cadena,16);

作为替代方案,您可以遍历字符串中的字符并调用Character.digit(c,16)它们(如果它们中的任何一个返回-1它不是有效的十六进制数字)。如果字符串太大而无法放入 a 中,这将特别有用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]+");
于 2012-07-11T02:05:57.710 回答
32

对异常的可怕滥用。永远不要这样做!(不是我,是 Josh Bloch 的 Effective Java)。无论如何,我建议

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

private boolean isHexadecimal(String input) {
    final Matcher matcher = HEXADECIMAL_PATTERN.matcher(input);
    return matcher.matches();
}
于 2012-12-02T08:05:09.180 回答
17

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

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

我对这个线程中提供的其他答案的不满是,如果字符串的长度很大,它也会抛出异常。因此,如果您正在测试 MAC 地址是否由有效的十六进制组成,则它不是很有用。

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

于 2014-09-13T06:50:56.800 回答
10

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

private static boolean isHexNumber (String cadena) {
  try {
    Long.parseLong(cadena, 16);
    return true;
  }
  catch (NumberFormatException ex) {
    // Error handling code...
    return false;
  }
}
于 2012-07-11T02:54:29.420 回答
10

这里有一些用于不同选项和执行时间结果的代码(JDK 11):

execution time isHex1: 3670 ms
execution time isHex2: 3294 ms
execution time isHex3: 3946 ms
execution time regex: 31288 ms

测试代码:

public class HexPerformanceTest {
    @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);

        Predicate<String> isHex1Test = testString -> {
            boolean isHex = true;
            for (char c: testString.toCharArray()) {
                if (!isHex1(c)) {
                    isHex = false;
                    break;
                }
            }
            return isHex;
        };

        Predicate<String> isHex2Test = testString -> {
            boolean isHex = true;
            for (char c: testString.toCharArray()) {
                if (!isHex2(c)) {
                    isHex = false;
                    break;
                }
            }
            return isHex;
        };

        Predicate<String> isHex3Test = testString -> {
            boolean isHex = true;
            for (char c: testString.toCharArray()) {
                if (!isHex3(c)) {
                    isHex = false;
                    break;
                }
            }
            return isHex;
        };

        Pattern pattern = Pattern.compile("^[0-9a-fA-F]+$");
        Predicate<String> regexTest = testString -> {
            Matcher matcher = pattern.matcher(regexString);
            return matcher.matches();
        };

        System.out.println("execution time isHex1: " + milliseconds(regexString, isHex1Test, count) + " ms");
        System.out.println("execution time isHex2: " + milliseconds(regexString, isHex2Test, count) + " ms");
        System.out.println("execution time isHex3: " + milliseconds(regexString, isHex3Test, count) + " ms");
        System.out.println("execution time regex: " + milliseconds(regexString, regexTest, count) + " ms");
    }

    private long milliseconds(String testString, Predicate<String> hexTest, int count) {
        long start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            hexTest.test(testString);
        }
        return 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);
    }
}
于 2017-03-23T14:24:41.027 回答
1

无库方法

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;
}
于 2016-10-23T18:13:54.080 回答
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;
}
于 2012-07-11T09:37:16.027 回答
0

尝试这个。

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)如果您不允许该标志,则可以省略。

于 2021-12-10T15:04:46.180 回答