我有一个字节数组。 我希望将该数组的每个字节String转换为相应的十六进制值。

Java中是否有将字节数组转换为十六进制的函数?


当前回答

这是一条非常快的路。不需要外部库。

final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray();

    public static String encodeHexString( byte[] bytes ) {

        char[] hexChars = new char[bytes.length * 2];
        for (int j = 0; j < bytes.length; j++) {
            int v = bytes[j] & 0xFF;
            hexChars[j * 2] = HEXARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

其他回答

如果你喜欢流,这里有一个格式-连接方法的单表达式版本:

String hex = IntStream.range(0, bytes.length)
                      .map(i -> bytes[i] & 0xff)
                      .mapToObj(b -> String.format("%02x", b))
                      .collect(Collectors.joining());

遗憾的是没有类似Arrays::streamUnsignedBytes这样的方法。

我所发现的最快的方法是:

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);

你可以使用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>

如果你想要一个恒定宽度的十六进制表示,即0A而不是a,这样你就可以明确地恢复字节,尝试format():

StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
    result.append(String.format("%02X", bb));
}
return result.toString();

我不知道你说的字节字符串到底是什么意思,但这里有一些从字节到字符串的转换,反之亦然,当然官方文档上有更多

Integer intValue = 149;

对应的字节值为:

Byte byteValue = intValue.byteValue(); // this will convert the rightmost byte of the intValue to byte, because Byte is an 8 bit object and Integer is at least 16 bit, and it will give you a signed number in this case -107

从Byte变量中返回整数值:

Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer

从字节和整数到十六进制字符串: 我是这样做的:

Integer anInt = 149
Byte aByte = anInt.byteValue();

String hexFromInt = "".format("0x%x", anInt); // This will output 0x95
String hexFromByte = "".format("0x%x", aByte); // This will output 0x95

将字节数组转换为十六进制字符串: 据我所知,没有一个简单的函数可以将某个对象的数组中的所有元素转换为另一个对象的元素,所以你必须自己做。您可以使用以下函数:

从byte[]到String:

    public static String byteArrayToHexString(byte[] byteArray){
        String hexString = "";

        for(int i = 0; i < byteArray.length; i++){
            String thisByte = "".format("%x", byteArray[i]);
            hexString += thisByte;
        }

        return hexString;
    }

从十六进制字符串到字节[]:

public static byte[] hexStringToByteArray(String hexString){
    byte[] bytes = new byte[hexString.length() / 2];

    for(int i = 0; i < hexString.length(); i += 2){
        String sub = hexString.substring(i, i + 2);
        Integer intVal = Integer.parseInt(sub, 16);
        bytes[i / 2] = intVal.byteValue();
        String hex = "".format("0x%x", bytes[i / 2]);
    }

    return bytes;
}  

现在已经太迟了,但我希望这能帮助到其他人;)