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

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

  • 相关阅读:
    Visifire正式版(v1.1)发布
    [转]PSP机能强大!已能模拟运行WINDOWS系统?
    在Silverlight+WCF中应用以角色为基础的安全模式(一)基础篇之角色为基础的安全模式简介 Virus
    C#的加密解密算法,包括Silverlight的MD5算法 Virus
    MMORPG programming in Silverlight Tutorial (10)Implement the sprite’s 2D animation (Part IV)
    Game Script: Rescue Bill Gates
    MMORPG programming in Silverlight Tutorial (9)KeyFrame Animation
    MMORPG programming in Silverlight Tutorial (5)Implement the sprite’s 2D animation (Part II)
    MMORPG programming in Silverlight Tutorial (7)Perfect animation
    MMORPG programming in Silverlight Tutorial (3)Animate the object (Part III)
  • 原文地址:https://www.cnblogs.com/phdeblog/p/14000915.html
Copyright © 2011-2022 走看看