Java中使用Scanner将十六进制字符串转为字节数组失败求助
问题原因分析
你遇到的核心问题是Scanner的hasNextByte(16)方法不会自动识别十六进制的0x前缀。
Scanner默认以空白字符作为分隔符,当输入是0xAA 0xBB这类格式时,每个独立的token是0xAA——这个字符串包含了非十六进制有效字符x,导致hasNextByte(16)判定它无法被解析为十六进制byte,循环根本不会执行,最终自然返回空数组。
哪怕输入是不带前缀的AA BB CC,如果后续有带前缀的混合输入,同样会触发这个问题,所以得针对性处理前缀问题。
解决方案
针对带0x前缀和不带前缀的两种输入格式,这里提供两种实用的处理方式:
方式一:预处理输入字符串,移除0x前缀
先把输入中的所有0x(或0X)前缀清除,让Scanner直接解析纯十六进制字符:
byte[] bytesFromString(String value) { // 移除所有大小写的0x前缀,不区分大小写 String cleanedInput = value.replaceAll("(?i)0x", ""); List<Byte> byteList = new ArrayList<>(); Scanner scanner = new Scanner(cleanedInput); while (scanner.hasNextByte(16)) { byteList.add(scanner.nextByte(16)); } // 转换为byte数组 byte[] result = new byte[byteList.size()]; for (int i = 0; i < byteList.size(); i++) { result[i] = byteList.get(i); } return result; }
方式二:手动处理每个Token,兼容两种格式
如果需要同时兼容带前缀和不带前缀的输入,可以逐个读取token,判断并移除前缀后再解析,还能顺便处理无效输入:
byte[] bytesFromString(String value) { List<Byte> byteList = new ArrayList<>(); Scanner scanner = new Scanner(value); while (scanner.hasNext()) { String token = scanner.next(); String hexStr = token; // 处理带0x/0X前缀的情况 if (token.startsWith("0x") || token.startsWith("0X")) { hexStr = token.substring(2); } try { // 用十六进制基数解析为byte byte b = Byte.parseByte(hexStr, 16); byteList.add(b); } catch (NumberFormatException e) { // 可选:处理无效的十六进制字符串,比如跳过或抛出自定义异常 System.err.println("无效的十六进制值:" + token); } } // 转换为byte数组 byte[] result = new byte[byteList.size()]; for (int i = 0; i < byteList.size(); i++) { result[i] = byteList.get(i); } return result; }
额外注意事项
- byte的范围限制:Java中byte的取值范围是
-128到127,如果输入的十六进制值超过这个范围(比如0xFF,对应十进制255),Byte.parseByte会抛出NumberFormatException。如果需要处理无符号byte,可以先解析为int再强转为byte,例如(byte) Integer.parseInt(hexStr, 16)。 - 大小写兼容:上述代码已经兼容大小写的
0X前缀和十六进制字符(比如aA也是有效的),因为Byte.parseByte和Scanner的hasNextByte(16)都不区分大小写。
内容的提问来源于stack exchange,提问作者yageek
相关产品推荐
相关产品推荐

