前言

      恰巧碰到了字节数组和整型的转换问题,特在此总结一下。将 int 按照小端法映射到 byte[] 中。即最低 8 位放在 byte[0] 中,依次类推。


一、int 转换为 byte[]

      这个实现起来比较简单,先保存最低的 8 位到 byte 数组中,然后不断的右移 8 位,每次保存低 8 位数据即可,参考代码:(这里包含一个 int 到 byte 的转换,转换规则是截取 int 的最低 8 位作为 byte 值)

    public static byte[] intToBytes(int a){
        byte[] ans=new byte[4];
        for(int i=0;i<4;i++)
            ans[i]=(byte)(a>>(i*8));//截断 int 的低 8 位为一个字节 byte,并存储起来
        return ans;
    }

二、测试代码

      为了验证转换结果,简单写了两个方法用来按位打印 int 和 byte,可参考如下:

    public static void intPrint(int a){//将 int 按位从左到右打印
        int count=0;
        for(int i=31;i>=0;i--){
            System.out.print((a>>i)&1);
            count++;
            if(count==4){//每四位为一组,用空格分开
                System.out.print(" ");
                count=0;
            }
        }
        System.out.println();
    }
    public static void bytePrint(byte a){//将 byte 按位从左到右打印
        int count=0;
        for(int i=7;i>=0;i--){
            System.out.print((a>>i)&1);
            count++;
            if(count==4){//每四位为一组,用空格分开
                System.out.print(" ");
                count=0;
            }
        }
        System.out.println();
    }

三、测试

      测试一下 int 到 byte[] 的正确性:用一个整数来测试一下,如下:

    public static void main(String[] args) {
        int c=968523,d=-65423;
        byte[] ans=intToBytes(d);
        intPrint(d);
        for(int i=0;i<4;i++)
            bytePrint(ans[i]);
            
    }

      输出结果为:
      1111 1111 1111 1111 0000 0000 0111 0001
      0111 0001
      0000 0000
      1111 1111
      1111 1111

      算法执行无误。

四、byte[] 转换为 int

      这个实现起来也比较简单, 每次将 byte 值保存到 int 的最低 8 位,然后 int 左移 8 位,继续保存新的 byte 值即可,参考代码:

    public static int bytesToInt(byte[] a){
        int ans=0;
        for(int i=0;i<4;i++){
            ans<<=8;//左移 8 位
            ans|=a[3-i];//保存 byte 值到 ans 的最低 8 位上
            intPrint(ans);
        }
        return ans;
    }

      验证一下(这一次采用整数 c 来说明问题,整数 d 恰好可以得到正确结果…):

    public static void main(String[] args) {
        int c=968523,d=-65423;
        byte[] ans=intToBytes(c);
        intPrint(c);
        for(int i=0;i<4;i++)
            bytePrint(ans[i]);

        int e=bytesToInt(ans);
    }

      输出结果:
      0000 0000 0000 1110 1100 0111 0100 1011
      0100 1011
      1100 0111
      0000 1110
      0000 0000
      0000 0000 0000 0000 0000 0000 0000 0000
      0000 0000 0000 0000 0000 0000 0000 1110
      1111 1111 1111 1111 1111 1111 1100 0111
      1111 1111 1111 1111 1100 0111 0100 1011

      Error:粗体显示和我们预料中的不太一样,其原因在于:语句 ans|=a[3-i];中,执行流程为:先将 byte a[3-i] 提升到 int ,然后再和 ans 取或操作,最后将结果赋给 ans。
      在提升的过程中包含一个 byte 到 int 的转换,转换规则:如果 byte 值为负,即最高位为 1,那么在前面补上 24 个 1 凑够 32 位作为 int 的值,如果 byte 值为正,即最高位为 0,那么在前面补上 24个 0 得到新的 int 值。

      为了每次在将 byte 转换为 int 时,前面都补上 0 ,这里可以将它先和 0xff 取 &。这里的 0xff 如果转换为 int 四字节的话为:0000 0000 0000 0000 0000 0000 1111 1111 。当然了,更加清晰的写法见下面代码。

      修改之后的代码如下:

    public static int bytesToInt(byte[] a){
        int ans=0;
        for(int i=0;i<4;i++){
            ans<<=8;
            ans|=(a[3-i]&0xff);
            /* 这种写法会看起来更加清楚一些:
            int tmp=a[3-i];
            tmp=tmp&0x000000ff;
            ans|=tmp;*/
            intPrint(ans);
        }
        return ans;
    }
    
    public static void main(String[] args) {
        int c=968523,d=-65423;
        byte[] ans=intToBytes(c);
        intPrint(c);
        for(int i=0;i<4;i++)
            bytePrint(ans[i]);

        int e=bytesToInt(ans);
        return;
    }

      输出结果:
      0000 0000 0000 1110 1100 0111 0100 1011
      0100 1011
      1100 0111
      0000 1110
      0000 0000
      0000 0000 0000 0000 0000 0000 0000 0000
      0000 0000 0000 0000 0000 0000 0000 1110
      0000 0000 0000 0000 0000 1110 1100 0111
      0000 0000 0000 1110 1100 0111 0100 1011

      能够看到可以得到正确结果。


总结

      需要注意的是:在 8 位 byte 提升到 32 位 int 时,由于数组在计算机中以补码形式存在,所以要区分正负的。正数前面补 0 ,负数前面补 1。而为了消除其差异性,仅保留我们所感兴趣的低 8 位,需要先将可能存在的 1 均变为 0,所以要先和 0xff 做 & 操作; 或者先提升到 int ,然后和0x000000ff 取 & 。

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐