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

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

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

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

我该怎么办?

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


当前回答

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

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

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

其他回答

我一直用的方法是

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

此方法根据空格分隔的十六进制值进行分割,但根据任何其他条件(例如分成两个字符的组)将字符串分割并不困难。

我想我会帮你的。我用一个类似的函数把它拼凑在一起,该函数以字符串形式返回数据:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

更新(2021年)- Java 17现在包括Java .util. hexformat(只花了25年):

HexFormat.of().parseHex(s)


For older versions of Java:

这里有一个解决方案,我认为比目前为止发布的任何解决方案都要好:

/* s must be an even-length string. */
public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

这是一种进步的原因:

前导零(与BigInteger不同)和负字节值(与byte . parsebyte不同)是安全的 不将String转换为char[],也不为每个字节创建StringBuilder和String对象。 没有可能不可用的库依赖项

如果不知道参数是否安全,可以通过assert或异常添加参数检查。

实际上,我认为BigInteger是很好的解决方案:

new BigInteger("00A0BF", 16).toByteArray();

编辑:正如海报所指出的,前导零不安全。

基于op投票的解决方案,下面的方案应该更有效一些:

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

因为:到char数组的初始转换省去了charAt中的长度检查