我有一个字节数组。 我希望将该数组的每个字节String转换为相应的十六进制值。
Java中是否有将字节数组转换为十六进制的函数?
我有一个字节数组。 我希望将该数组的每个字节String转换为相应的十六进制值。
Java中是否有将字节数组转换为十六进制的函数?
当前回答
使用BigInteger将byte[]转换为十六进制字符串的简单方法:
import java.math.BigInteger;
byte[] bytes = new byte[] {(byte)255, 10, 20, 30};
String hex = new BigInteger(1, bytes).toString(16);
System.out.println(hex); // ff0a141e
它是如何工作的?
内置的系统类java.math.BigInteger类(java.math.BigInteger)兼容二进制和十六进制数据:
它有一个构造函数BigInteger(signum=1, byte[])通过byte[]创建一个大整数(设置它的第一个参数signum=1以正确处理负字节) 使用BigInteger.toString(16)将大整数转换为十六进制字符串 要解析十六进制数,请使用new BigInteger("ffa74b", 16) -不能正确处理前导零
如果你想在十六进制结果中有前导零,检查它的大小,并在必要时添加缺少的零:
if (hex.length() % 2 == 1)
hex = "0" + hex;
笔记
使用new BigInteger(1, bytes),而不是new BigInteger(bytes),因为Java“被设计破坏了”,字节数据类型不包含字节,而是有符号的小整数[-128…127]。如果第一个字节是负的,BigInteger假设您传递了一个负的大整数。只需传递1作为第一个参数(signum=1)。
从十六进制转换回字节[]是棘手的:有时前导零进入产生的输出,它应该像这样被清除:
byte[] bytes = new BigInteger("ffa74b", 16).toByteArray();
if (bytes[0] == 0) {
byte[] newBytes = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, newBytes, 0, newBytes.length);
bytes = newBytes;
}
最后一个提示是如果字节[]有几个前导零,它们将丢失。
其他回答
如果您乐于使用外部库,则org.apache.commons.codec.binary.Hex类有一个encodeHex方法,该方法接受一个字节[]并返回一个char[]。这个方法比format选项快得多,并且封装了转换的细节。还附带了一个decodeHex方法,用于相反的转换。
我所发现的最快的方法是:
private static final String HEXES = "0123456789ABCDEF";
static String getHex(byte[] raw) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
它比String.format快50倍。如果你想测试它:
public class MyTest{
private static final String HEXES = "0123456789ABCDEF";
@Test
public void test_get_hex() {
byte[] raw = {
(byte) 0xd0, (byte) 0x0b, (byte) 0x01, (byte) 0x2a, (byte) 0x63,
(byte) 0x78, (byte) 0x01, (byte) 0x2e, (byte) 0xe3, (byte) 0x6c,
(byte) 0xd2, (byte) 0xb0, (byte) 0x78, (byte) 0x51, (byte) 0x73,
(byte) 0x34, (byte) 0xaf, (byte) 0xbb, (byte) 0xa0, (byte) 0x9f,
(byte) 0xc3, (byte) 0xa9, (byte) 0x00, (byte) 0x1e, (byte) 0xd5,
(byte) 0x4b, (byte) 0x89, (byte) 0xa3, (byte) 0x45, (byte) 0x35,
(byte) 0xd6, (byte) 0x10,
};
int N = 77777;
long t;
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 50
}
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
StringBuilder hex = new StringBuilder(2 * raw.length);
for (byte b : raw) {
hex.append(String.format("%02X", b));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 2535
}
}
}
编辑:刚刚发现一些东西只是稍微快一点,保持在一行,但与JRE 9不兼容。使用风险自负
import javax.xml.bind.DatatypeConverter;
DatatypeConverter.printHexBinary(raw);
Use
Integer.toHexString((int)b);
BigInteger n = new BigInteger(byteArray);
String hexa = n.toString(16);
你可以使用Bouncy Castle Provider库中的方法:
org.bouncycastle.util.encoders.Hex.toHexString(byteArray);
Bouncy Castle Crypto包是一个Java实现 加密算法。这个jar包含JCE提供程序和 用于JDK 1.5的Bouncy Castle Cryptography API的轻量级API JDK 1.8。
Maven的依赖:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
或来自Apache Commons Codec:
org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);
Apache Commons Codec包包含简单的编码器和解码器 用于各种格式,如Base64和十六进制。除了 这些编码器和解码器被广泛使用,编解码器包也有 维护语音编码实用程序的集合。
Maven的依赖:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>