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

时间:2015-02-19 14:50:52

标签: java android string int hex

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

我在另一个课程中创​​建int[]并通过通过 msg.obj获取。我在Hex中得到了一些值但不确定它们是否正确。

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

2 个答案:

答案 0 :(得分:2)

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

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

  2. 您希望确保Integer.toHexString的输出始终用前面的零填充,因此它的长度始终为8个字符(因为4字节长的每个字节需要2字符)。否则,数组{1,2,3}和数组{291}都会为您提供相同的字符串 - 123

  3. 这是一个快速而肮脏的工作代码示例

        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
    

答案 1 :(得分:1)

@ Malt的答案肯定会突出显示代码的问题:它不会填充int十六进制值;并且您使用a & 0xff将int屏蔽为仅使用最后8位。您的原始问题意味着您只在每个byte的最后int之后,但它确实不清楚。

您说您每秒都会从远程对象获得结果。在具有大型阵列的慢速计算机上,使用您的方法(或者更确切地说是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(微基准测试results here)对原始方法进行测试显示,这比快了大约11倍(警告:在我的机器上)。 编辑对于有兴趣运行此功能并比较结果的任何人,都有gist here的源代码。

即使对于单个元素数组

原来的微基准测试使用Caliper,因为我当时正在试用它。我已将其改写为使用JMH。在这样做的过程中,我发现results I linked to并在此处复制时最初使用的数组只为每个0元素填充了int。这导致JVM优化长度为&gt;的数组的AltConverter代码。 1AltConverter相比,SimpleConverter产生了10倍至11倍的人为改进。 JMH和Caliper对有缺陷和校正的基准产生非常相似的结果。 (更新了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 |

免责声明:微型基准测试在实际应用程序中依赖于性能指标是危险的,但是卡尺是一个很好的基准测试框架,jmh更好。性能差异 10x 4x,其中非常小的标准偏差,卡尺良好的t检验结果足以表明即使在更复杂的应用中,性能也会提高< / em>的