草庐IT

Java 字节数组(byte[])和整型(int)的相互转换

消逝者 2023-04-27 原文

文章目录


前言

      恰巧碰到了字节数组和整型的转换问题,特在此总结一下。将 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 取 & 。

有关Java 字节数组(byte[])和整型(int)的相互转换的更多相关文章

  1. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  2. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  3. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  4. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  5. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  6. ruby - 将散列转换为嵌套散列 - 2

    这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[

  7. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  8. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  9. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  10. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

随机推荐