我正在寻找一种方法来转换一个长字符串(从转储),它表示十六进制值到字节数组。

我不可能比在这里发布同样问题的人表达得更好。

但是为了保持它的原创性,我将以自己的方式表达它:假设我有一个字符串“00A0BF”,我希望将其解释为

byte[] {0x00,0xA0,0xBf}

我该怎么办?

我是一个Java新手,最后使用BigInteger并注意前导十六进制零。但我认为它很丑,我肯定我错过了一些简单的东西。


当前回答

我喜欢这个角色。数位解,我是这样解的

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}

其他回答

如果您的需求不仅仅是偶尔的转换,那么您可以使用HexUtils。

例子:

byte[] byteArray = Hex.hexStrToBytes("00A0BF");

这是最简单的情况。您的输入可能包含分隔符(如MAC地址、证书指纹等),您的输入可能是流式的,等等。在这种情况下,引入像HexUtils这样的外部库(无论多么小)变得更容易。

在JDK 17中,HexFormat类将满足大多数需求,而对HexUtils这样的类的需求将大大减少。然而,HexUtils仍然可以用于一些事情,比如从十六进制(流)转换非常大的量或漂亮的十六进制打印(想想有线转储),这是JDK HexFormat类不能做的。

(完全披露:我是HexUtils的作者)

common -codec中的Hex类应该为您做到这一点。

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

java中的BigInteger()方法。数学很慢,不值得推荐。

整数。parseInt (HEXString, 16)

可以导致问题与某些字符没有 转换为数字/整数

良好的工作方法:

Integer.decode("0xXX") .byteValue()

功能:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

玩得开心,好运

如果您偏好Java 8流作为编码风格,那么可以使用JDK原语来实现。

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

如果不介意捕获IOException,收集器连接函数中的,0,s2.size()参数可以省略。

现在可以在guava中使用BaseEncoding来实现这一点。

BaseEncoding.base16().decode(string);

反过来使用

BaseEncoding.base16().encode(bytes);