zoukankan      html  css  js  c++  java
  • Java十六进制字符串与二进制数组互转、&0xff的作用

    十六进制字符串转字节数组

    /**
         * 功能: 十六进制字符串转字节数组
         * @param hexString 十六进制字符串
         * @return 字节数组
         */
        public static byte[] convertHexStringToBytes(String hexString){
            //判空
            if(hexString == null || hexString.length() == 0) {
                return null;
            }
    
            //合法性校验
            if(!hexString.matches("[a-fA-F0-9]*") || hexString.length() % 2 != 0) {
                return null;
            }
    
            //计算
            int mid = hexString.length() / 2;
            byte[]bytes = new byte[mid];
            for (int i = 0; i < mid; i++) {
                bytes[i] = Integer.valueOf(hexString.substring(i * 2, i * 2 + 2), 16).byteValue();
            }
    
            return bytes;
        }

    字节数组转十六进制字符串

        /**
         * 字节数组转16进制数
         * @param bytes 字节数组
         * @return 返回值
         */
        public static String convertBytesToHexString(byte[]bytes) {
            StringBuilder res = new StringBuilder("");
            for (byte aByte : bytes) {
                String temp = Integer.toHexString(aByte & 0xff);
                if (temp.length() == 1) {
                    temp = '0' + temp;
                }
                res.append(temp);
            }
            return res.toString().toUpperCase();
        }

    整数转化为十六进制字符串

     /**
         * 功能:将整数转化为合法的十六进制字符串
         * @param source 整数
         * @param len 至少占多少个字节
         * @return 十六进制数
         *
         * 说明:为什么要有len?
         * 某些场景需要指定大小的二进制字符串(这里的大小指的是转化为字节数组后所占大小)
         * 例如,现在需要把1这个整数转化为十六进制数,
         * 如果len为1,结果为 01
         * 如果len为2,结果为 0001
         *
         * 但是len不限制大小,比如len设置为1,source为125120,那么结果仍然为1e8c0,
         * 不会截断结果
         */
        public static String convertIntToHexString(int source, int len) {
            //一个字节占两位,所以要乘以2
            len <<= 1;
            StringBuilder res = new StringBuilder(Integer.toHexString(source));
            int comp = len - res.length();
    
            //位数不足,需要补0
            if(comp > 0) {
                for (int i = 0; i < comp; i++) {
                    res.insert(0, "0");
                }
            }
    
            return res.toString();
        }

    个人理解

    上文提及的“合法十六进制字符串”指的是什么?

    需要满足如下条件:

    1、只能包含数字以及字母ABCDEF(包含大小写)

    2、字符的个数必须是双数,比如“1”只能写成“01”

    &0xff 到底有什么含义?

    首先我们先了解一下基本作用

    1 & 0 = 0

    1 & 1 = 1

    0 & 0 = 0

    计算机中二进制数都是以补码的形式存在

    a & 0xff 表示取 a 补码的后八位。

    16进制字符串的范围是 0x00 到 0xff,0到255

    java中的byte是有符号的,一个byte表示的范围是  -128到127。

    而在这里,我们不需要byte的符号属性,只需要它老老实实的表示0到255即可,所以不得不将128到255之间的数据做一个映射。

    换句话说,11111111(补码), 如果最高位作为符号位, 它是-1,如果不作为符号位,那就能表示255.

        public static void main(String[] args) {
              byte a = -1;
              int b = a & 0xff;
              System.out.println(a);
              System.out.println(b);
        }

    结果是:

    -1
    255

    a & 0xff的返回值是int,也就是说,将a这个字节的补码原封不动的拿出来,放到int中。

    因为int 是四个字节,我们现在只用了两个字节,自然触碰不到符号位,这么一操作,就可以将 -1 映射成 255。

    这样就可以理解字节转字符串中的这个转换了:

    Integer.toHexString(aByte & 0xff);

    简而言之,我们确实需要存256个数,但是范围是0-255,而不是 -128-127,因为java不支持unsigned byte这种数据类型,所以我们需要借助容量更大的int完成这一转换。

    换句话说,如果java支持无符号byte,就不需要做这种转换了。(C#中的byte就是没有符号的,sbyte才是有符号的)

    关于原码、补码、反码的相关概念,推荐文章:  https://zhuanlan.zhihu.com/p/91967268

    如有错误,恳请批评指正!

  • 相关阅读:
    mescroll vue tab页实现切换刷新列表
    路由权限配置
    js实现拖拽
    .eslintrc.js
    vue-cli项目中使用mock结合axios-mock-adapter生成模拟数据【转】
    原型模式
    设计模式简介
    @RequestParam @RequestBody @PathVariable 等参数绑定注解详解
    spring定时任务执行两次
    java反射--注解的定义与运用以及权限拦截
  • 原文地址:https://www.cnblogs.com/phdeblog/p/14000915.html
Copyright © 2011-2022 走看看