如何在Java中将字节数组转换为十六进制格式

13

我知道您可以使用 printf,也可以使用 StringBuilder.append(String.format("%x", byte)) 将值转换为十六进制值并在控制台上显示它们。但我希望能够实际格式化字节数组,以便每个字节都以十六进制而不是十进制显示。

这里是我已经编写的代码部分,其中包含了前两种方法:

if(bytes > 0)
    {
        byteArray = new byte[bytes]; // Set up array to receive these values.

        for(int i=0; i<bytes; i++)
        {
            byteString = hexSubString(hexString, offSet, CHARSPERBYTE, false); // Isolate digits for a single byte.
            Log.d("HEXSTRING", byteString);

            if(byteString.length() > 0)
            {
                byteArray[i] = (byte)Integer.parseInt(byteString, 16); // Parse value into binary data array.
            }
            else
            {
                System.out.println("String is empty!");
            }

            offSet += CHARSPERBYTE; // Set up for next word hex.    
        }

        StringBuilder sb = new StringBuilder();
        for(byte b : byteArray)
        {
            sb.append(String.format("%x", b));
        }

        byte subSystem = byteArray[0];
        byte highLevel = byteArray[1];
        byte lowLevel = byteArray[2];

        System.out.println("Byte array size: " + byteArray.length);
        System.out.printf("Byte 1: " + "%x", subSystem);
        System.out.printf("Byte 2: " + "%x", highLevel);
        System.out.println("Byte 3: " + lowLevel);
        System.out.println("Byte array value: " + Arrays.toString(byteArray));
        System.out.println("Byte array values as HEX: " + sb.toString());
    }
    else
    {
        byteArray = new byte[0]; // No hex data.

        //throw new HexException();
    }

    return byteArray;

被分割成字节数组的字符串是:

"1E2021345A2B"

但在控制台上显示为十进制:

"303233529043"

请问有人能告诉我如何将实际值转换为十六进制并以自然的方式显示出来吗? 预先感谢您的帮助。


为什么不直接调用 Integer.parseInt(sb.toString(), 16) 呢? - Luke
4个回答

31

1
我正在使用Android Java,但Android不支持这个。有没有其他的解决方法? - James Meade
2
我找到的最短的方式。 - Alex
VGR的答案同样适用于Android,而且更简单。 - Ethan
@JamesMeade 对于 Android,请参考 VGR 的解决方案 - Paul Vargas
对于商业应用程序而言,javax.xml.bind.DatatypeConverter通常是最佳选择。 - JRA_TLL

26

String.format 实际上使用了 java.util.Formatter 类。不要使用 String.format 方法,而是直接使用 Formatter:

Formatter formatter = new Formatter();
for (byte b : bytes) {
    formatter.format("%02x", b);
}
String hex = formatter.toString();

从Java 17开始,HexFormat可以在一行代码中实现此功能:

String hex = HexFormat.of().formatHex(bytes);

1
这是我能找到的最短、最简单的答案,不依赖于非标准库。非常优秀!!! - Ethan
迄今为止最干净的解决方案。谢谢!值得一提的是,您可以将 x 大写并在大写后添加一个空格,以使其更易读。 - Victor Queiroz
如果最后一个字节小于16,这个会补零吗? - Constance Eustace
@ConstanceEustace %02x 中的 0 表示“如果需要确保有两个数字,则用零填充”。来自文档:“如果给出了 '0' 标志,则输出将在基数指示器或符号(如果存在)之后使用前导零填充到字段宽度。” - VGR

6
我做法是:
  private static final char[] HEX_CHARS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A',
      'B', 'C', 'D', 'E', 'F' };

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

我想让两个字符占用一个字节。因此,对于我的示例,我有一个包含6个元素的字节数组。 - James Meade
0x31和0x45已经是十六进制数了,它们的“hex”表示不是1E,而实际上是"31"和"45"。 - Tamas
我知道它们是十六进制数,但当这些十六进制数分别为31和45时,1E的十六进制值叫什么?其中1代表31,E代表45。 - James Meade
1
这个视频讲的正是关于数字系统之间的转换:http://www.youtube.com/watch?v=Fpm-E5v6ddc - Tamas
这些视频非常有帮助,现在我理解得更好了,谢谢。 - James Meade
显示剩余5条评论

2

试试这个

byte[] raw = some_bytes;
javax.xml.bind.DatatypeConverter.printHexBinary(raw)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接