Java –如何将字节数组转换为十六进制 蔚落 2023-02-15 05:13 687阅读 0赞 ![Java字节\[\]到十六进制][Java]![Java字节\[\]到十六进制][Java] 本文介绍了几种将字节数组或`byte[]`转换为[十六进制][Link 1] (基数16或十六进制)字符串表示形式的方法。 1. `String.format` 2. `Integer.toHexString` 3. Apache Commons编解码器– `commons-codec` 4. Spring Security加密– `spring-security-crypto` 5. 按位移位和屏蔽。 (教育目的) > **注意** > Apache Commons-Codec和Spring Security Crypto模块都使用类似的`5. Bitwise shifting and masking`技术将字节数组转换为十六进制字符串,请研究下面的源代码,这对于教育目的很有用。 ## 1. String.format%02x ## 此`String.format`是将字节数组转换为十六进制的最简单且显而易见的方法, `%02x`用于小写十六进制, `%02X`大写十六进制。 ByteToHexExample1.java package com.mkyong.crypto.bytes; import java.nio.charset.StandardCharsets; public class ByteToHexExample1 { public static String hex(byte[] bytes) { StringBuilder result = new StringBuilder(); for (byte aByte : bytes) { result.append(String.format("%02x", aByte)); // upper case // result.append(String.format("%02X", aByte)); } return result.toString(); } public static void main(String[] args) { String input = "a"; System.out.println(hex(input.getBytes(StandardCharsets.UTF_8))); } } 输出量 Terminal 61 ## 2. Integer.toHexString ## 此`Integer.toHexString(int i)`接受一个`int`作为参数,并返回一个十六进制字符串。 密钥是将`byte`转换为`int`和带有`0xff`掩码以防止符号扩展 。 ByteToHexExample2.java package com.mkyong.crypto.bytes; import java.nio.charset.StandardCharsets; public class ByteToHexExample2 { public static String hex(byte[] bytes) { StringBuilder result = new StringBuilder(); for (byte aByte : bytes) { int decimal = (int) aByte & 0xff; // bytes widen to int, need mask, prevent sign extension // get last 8 bits String hex = Integer.toHexString(decimal); if (hex.length() % 2 == 1) { // if half hex, pad with zero, e.g \t hex = "0" + hex; } result.append(hex); } return result.toString(); } public static void main(String[] args) { String input = "a"; System.out.println(hex(input.getBytes(StandardCharsets.UTF_8))); } } 输出量 Terminal 61 ## 3. Apache Commons编解码器 ## 我们可以使用`Hex.encodeHex`将`byte[]`转换为十六进制字符串,或使用`Hex.decodeHex`将十六进制字符串转换为`byte[]` 。 ByteToHexExample3 package com.mkyong.crypto.bytes; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Hex; import java.nio.charset.StandardCharsets; public class ByteToHexExample3 { public static String hex(byte[] bytes) { char[] result = Hex.encodeHex(bytes); return new String(result); } public static String unhex(String hex) throws DecoderException { return new String(Hex.decodeHex(hex)); } public static void main(String[] args) throws DecoderException { String input = "a"; String hex = hex(input.getBytes(StandardCharsets.UTF_8)); System.out.println(hex); // 61 String unhex = unhex(hex); System.out.println(unhex); // a } } Maven。 pom.xml <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.14</version> </dependency> ## 4. Spring Security加密 ## 在Spring Security中,我们可以使用`Hex.encode`将`byte[]`转换为十六进制字符串。 ByteToHexExample4.java package com.mkyong.crypto.bytes; import org.springframework.security.crypto.codec.Hex; import java.nio.charset.StandardCharsets; public class ByteToHexExample4 { public static void main(String[] args) { String input = "a"; char[] encode = Hex.encode(input.getBytes(StandardCharsets.UTF_8)); String hex = new String(encode); System.out.println(hex); // 61 byte[] decode = Hex.decode(hex); System.out.println(new String(decode)); // a } } Maven。 pom.xml <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-crypto</artifactId> <version>5.3.2.RELEASE</version> </dependency> ## 5.按位移位和屏蔽。 ## 下面的源代码来自[Spring Security Crypto][]模块, [Apache Commons Codes][]使用类似的技术将字节数组转换为十六进制字符串,但有一些小的变化,例如不同的变量名或长度计算,其核心思想是相同的。 5.1十六进制编码。 Hex.java package org.springframework.security.crypto.codec; //... private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static char[] encode(byte[] bytes) { final int nBytes = bytes.length; char[] result = new char[2 * nBytes]; // 1 hex contains two chars // hex = [0-f][0-f], e.g 0f or ff int j = 0; for (byte aByte : bytes) { // loop byte by byte // 0xF0 = FFFF 0000 result[j++] = HEX[(0xF0 & aByte) >>> 4]; // get the top 4 bits, first half hex char // 0x0F = 0000 FFFF result[j++] = HEX[(0x0F & aByte)]; // get the bottom 4 bits, second half hex char // combine first and second half, we get a complete hex } return result; } 困难的部分是要理解以下两个语句。 HEX[(0xF0 & aByte) >>> 4]; HEX[(0x0F & aByte)]; 5.1.1 `HEX[(0xF0 & aByte) >>> 4]` (十六进制的前半部分) 例如,一个二进制字符`a`为`0110 0001` , `bitwise AND` `0xF0` ,它变为`0110 0000` 。 0110 0001 # 1 hex = 2 chars [0-f][0-f] # In this case, hex = [0110][0001] 0110 0001 # 0110 = first half hex, 0001 = second half hex & FFFF 0000 # 0xF0 = FFFF 0000 , bitwise AND operator. 0110 0000 # result 0110 0000 逻辑右移4位`0110 0000 >>> 4` ,它变为`0000 0110` 。 阅读此Java >>和>>>按位移位运算符 。 0110 0000 | ???? 0110 | 0000 # >>> 4 0000 0110 | 0000 # >>> 4 (logical right shift, zero extension) 0000 0110 # result, the first half hex 将此二进制数`0000 0110`转换为十进制,它是`6` ,查看变量`static final char[] HEX` ,索引6的值是6,十六进制的前半部分是6。 5.1.2 `HEX[(0x0F & aByte)]` (后半十六进制) 相同的字符`a`二进制为`0110 0001` , `bitwise AND` `0x0F` 。 0110 0001 # 0110 = first half hex, 0001 = second half hex & # bitwise AND operator. 0000 FFFF # 0x0F = 0000 FFFF 0000 0001 # result 0000 0001 将此二进制数`0000 00001`转换为十进制,为`1` ,再次查看变量`static final char[] HEX` ,索引1的值为1,十六进制的后半部分为1。 我们将十六进制的上半部分和下半部分相结合,即6 + 1,即为`61` 。 对于字符`a` ,十六进制为`61` 。 5.2十六进制解码。 Hex.java package org.springframework.security.crypto.codec; //... private static final char[] HEX = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; public static byte[] decode(CharSequence s) { int nChars = s.length(); if (nChars % 2 != 0) { throw new IllegalArgumentException( "Hex-encoded string must have an even number of characters"); } byte[] result = new byte[nChars / 2]; // 1 hex = 2 char for (int i = 0; i < nChars; i += 2) { // step 2, 1 hex = 2 char int msb = Character.digit(s.charAt(i), 16); // char -> hex, base16 int lsb = Character.digit(s.charAt(i + 1), 16); if (msb < 0 || lsb < 0) { throw new IllegalArgumentException( "Detected a Non-hex character at " + (i + 1) + " or " + (i + 2) + " position"); } result[i / 2] = (byte) ((msb << 4) | lsb); } return result; } } 例如,相同的十六进制`61`字符`a` 。 `Character.digit`是JDK API,将`char`转换为16或16进制并返回`int` 。 int msb = Character.digit(s.charAt(i), 16); // msb = 6 int lsb = Character.digit(s.charAt(i + 1), 16); // lsb = 1 * `msb`代表[最高有效位][Link 2] (或高阶位或最左位)。 * `lsb`代表[最低有效位][Link 3] (或最右边的位)。 > **注意** > `msb`和`lsb`变量名称有些奇怪,我认为作者指的是前4位和后4位。 在Java int `6` ,二进制值为`0000 0110` ; 对于int `1`二进制是`0000 0001` (byte) ((msb << 4) | lsb); // in this example, msb = 6, lsb = 1 # (byte) ((msb << 4) | lsb); | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0110 | # msb, 6 is an int, 32-bit # (byte) ((msb << 4) | lsb); # (byte) ((6 << 4) | 1); # <<-- 4 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0110 ???? | # 6 << 4 0000 | 0000 0000 | 0000 0000 | 0000 0000 | 0110 0000 | # left shift, ignore sign, zero extension. | 0000 0000 | 0000 0000 | 0000 0000 | 0110 0000 | # final msb # bitwise | operator, bitwise inclusive OR | 0000 0000 | 0000 0000 | 0000 0000 | 0000 0001 | # lsb = 1 | 0000 0000 | 0000 0000 | 0000 0000 | 0110 0001 | # msb | lsb = 0110 0001 | 0110 0001 | # (byte) (msb|lsb) , down cast from int to byte 8-bit 最终的二进制文件是`0110 0001` 。 此代码段将二进制字符串转换为字符串,对于二进制`0110 0001` ,该字符串为`a` 。 int charCode = Integer.parseInt("01100001", 2); System.out.println(charCode); // 97, look ascii table String str = Character.toString((char) charCode); System.out.println(str); // output = a 谢谢阅读。 ## 参考文献 ## * [维基百科-十六进制][Link 1] * [维基百科–按位运算][Link 4] * Java Sign扩展 * Java >>和>>>按位移位运算符 * [Oracle –按位和移位运算符][Oracle] * [Spring安全加密][Spring Security Crypto] 标签: [0xff][] [base16][] [字节数组][Link 5] [十六进制][Link 6] [安全性][Link 7] > 翻译自: [https://mkyong.com/java/java-how-to-convert-bytes-to-hex/][https_mkyong.com_java_java-how-to-convert-bytes-to-hex] [Java]: http://imgconvert.csdnimg.cn/aHR0cHM6Ly9ta3lvbmcuY29tL3dwLWNvbnRlbnQvdXBsb2Fkcy8yMDE4LzA5L2phdmEtYnl0ZS1hcnJheXMtdG8taGV4LnBuZw?x-oss-process=image/format,png [Link 1]: https://en.wikipedia.org/wiki/Hexadecimal [Spring Security Crypto]: https://docs.spring.io/spring-security/site/docs/5.0.x/reference/html/crypto.html [Apache Commons Codes]: http://commons.apache.org/proper/commons-codec/ [Link 2]: https://en.wikipedia.org/wiki/Bit_numbering#Most_significant_bit [Link 3]: https://en.wikipedia.org/wiki/Bit_numbering#Least_significant_bit [Link 4]: https://en.wikipedia.org/wiki/Bitwise_operation [Oracle]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html [0xff]: https://mkyong.com/tag/0xff/ [base16]: https://mkyong.com/tag/base16/ [Link 5]: https://mkyong.com/tag/byte-array/ [Link 6]: https://mkyong.com/tag/hex/ [Link 7]: https://mkyong.com/tag/security/ [https_mkyong.com_java_java-how-to-convert-bytes-to-hex]: https://mkyong.com/java/java-how-to-convert-bytes-to-hex/
还没有评论,来说两句吧...