如何将int数组转换为十六进制字符串

How to convert int array to hex string

我想将 int 数组转换为十六进制字符串。我不确定我这样做是否正确。

我在另一个 class 中创建了一个 int[] 并通过 通过 msg.obj 获取它。我得到了一些十六进制值,但不确定它们是否正确。

int[] readBuf = (int[]) msg.obj; //int array is in another class 
StringBuffer output=new StringBuffer();
for (int a:readBuf) {
    int val1 = a & 0xff;
    output.append(Integer.toHexString(val1));
}   
dataView.setText(output);

假设我理解你的意图,代码有两个问题:

  1. int val1 = a & 0xff; 您只使用了 int 的最后一个字节。如果要转换整个整数,请删除 &0xff.

  2. 你要确保 Integer.toHexString 的输出总是在前面用零填充,所以它的长度总是 8 个字符(因为 4 字节 long int 的每个字节都需要 2人物)。否则数组 {1,2,3} 和数组 {291} 都会给你相同的字符串 - 123.

这是一个快速但粗略的工作代码示例

    public static String byteToUnsignedHex(int i) {
        String hex = Integer.toHexString(i);
        while(hex.length() < 8){
            hex = "0" + hex; 
        }
        return hex;
    }

    public static String intArrToHex(int[] arr) {
        StringBuilder builder = new StringBuilder(arr.length * 8);
        for (int b : arr) {
            builder.append(byteToUnsignedHex(b));
        }
        return builder.toString();
    }

    public static void main(String[] args){
        System.out.println(intArrToHex(new int[]{1,2,3}));
        System.out.println(intArrToHex(new int[]{291}));
        System.out.println(intArrToHex(new int[]{0xFFFFFFFF}));
    }

输出:

000000010000000200000003
00000123
ffffffff

@Malt 的回答肯定突出了您的代码的问题:它没有用 0 填充 int 十六进制值;并且您使用 a & 0xff 屏蔽 int 以仅获取最后 8 位。你最初的问题暗示你只是在每个 int 中的最后一个 byte 之后,但它真的不清楚。

你说你每秒从你的远程对象中得到结果。在具有大型阵列的慢速机器上,使用您的方法(或者更确切地说是 Malt 的更正版本)方法将长 int[] 转换为十六进制字符串可能需要大量毫秒。

一种更快的方法是使用移位从每个 int 中获取每个 4 位 nibble,并从静态十六进制查找数组中获取适当的十六进制字符(注意这确实base-16 编码,你会从 base-64 编码):

之类的东西中得到更短的字符串
public class AltConverter {
    final protected static char[] encoding = "0123456789ABCDEF".toCharArray();
    public String convertToString(int[] arr) {
        char[] encodedChars = new char[arr.length * 4 * 2];
        for (int i = 0; i < arr.length; i++) {
            int v = arr[i];
            int idx = i * 4 * 2;
            for (int j = 0; j < 8; j++) {
                encodedChars[idx + j] = encoding[(v >>> ((7-j)*4)) & 0x0F];
            }
        }
        return new String(encodedChars);
    }
}

使用 caliper (microbenchmark results here) shows this is around 11x faster (caveat: on my machine). EDIT For anyone interested in running this and comparing the results, there is a gist here 和源代码测试此方法与您的原始方法。

即使对于单个元素数组

原始微基准使用 Caliper as I happened to be trying it out at the time. I have rewritten it to use JMH. While doing so I found that the results I linked to and copied here originally used an array that was only ever filled with 0 for each int element. This caused the JVM to optimise the AltConverter code for arrays with length > 1 yielding artificial 10x to 11x improvements in AltConverter vs SimpleConverter. JMH and Caliper produce very similar results for both the flawed and corrected benchmark. (Updated benchmark project for maven eclipse here).

这大约快 2 到 4 倍,具体取决于数组长度(在我的机器上™)。平均运行时间结果(以 ns 为单位)为:

Average run times in nanoseconds
Original method: SimpleConverter
New method: AltConverter
 | N          |    Alt / ns | error / ns | Simple / ns | Error / ns | Speed up |
 | ---------: |  ---------: | ---------: | ----------: | ---------: | -------: |
 | 1          |          30 |          1 |          61 |          2 |     2.0x |
 | 100        |         852 |         19 |       3,724 |         99 |     4.4x |
 | 1000       |       7,517 |        200 |      36,484 |        879 |     4.9x |
 | 1000,0     |      82,641 |      1,416 |     360,670 |      5,728 |     4.4x |
 | 1000,00    |   1,014,612 |    241,089 |   4,006,940 |     91,870 |     3.9x |
 | 1000,000   |   9,929,510 |    174,006 |  41,077,214 |  1,181,322 |     4.1x |
 | 1000,000,0 | 182,698,229 | 16,571,654 | 432,730,259 | 13,310,797 |     2.4x |

免责声明:在现实世界的应用程序中,依赖微基准测试作为性能指标是危险的,但 caliper 是一个很好的基准测试框架, jmh 恕我直言更好。 10x 4x 的性能差异,非常小的标准偏差,在 caliper 中,良好的 t 检验结果足以表明良好的性能提升,即使在更复杂的应用程序中.