Apache工具包方法——Hex.encodeHexString(byte[] data)源码浅析

【2019-07-02 注:标题是Hex.encodeHexString(byte[] data) 的源码解析,但在实际测试过程中,改了方法名称,内部实现还是完全一样的。】

最近正在研究加密的相关方法和思想,有时候会用到byte类型的数组密钥或者密文,由于经常会遇到要将这鬼东西与数据库进行存取操作的情况,并且大多数情况都是将这样的byte数组转化为字符串进行存储的,因此用到了题目中的API,现对其源码实现进行总结和思考。

public static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', 
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };public static String byte2HexString(final byte[] data) {final int l = data.length;final char[] out = new char[l << 1];// two characters form the hex value.for (int i = 0, j = 0; i < l; i++) {out[j++] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4];out[j++] = DIGITS_UPPER[0x0F & data[i]];}return new String(out);
}

源码中我们注意到了DIGITS_UPPER这个char[] 数组,事实上这个byte2HexString的实现原理是:将data中的每个byte元素拆分为两个十六进制数,作为DIGITS_UPPER数组的下标,然后找到其对应的char字符,组装成一个char[]数组。

测试用例

	public static void main(String[] args) {byte[] org = {1, 2, 3, 15, 10, 16, 17, 32, 0, 8};// 01 02 03 0F 0A 10 11 20 00 08String hexstr = DataConvertUtil.byte2HexString(org);System.out.println("转化结果:" + hexstr);}

执行结果:

转化结果:0102030F0A1011200008

 结果是完全没有问题的,下面是图解(20190702追加图解)

首先data.length获取到data数组的元素个数(数组长度也就是元素的个数),然后再初始化一个新的char数组,out = new char[l << 1];这里值得注意的是char数组的长度,源码中用移位运算来表示,事实上在我上一篇文章中已经写得很明确,将一个数左移一位等价于将这个数 ×2,也就是说这个char数组的长度是data数组的二倍!为什么?原因如下:data中的每个元素都是byte类型,每个元素8个bit,分为高四位低四位,而每四位就可以表示一个0x0到0x15的十六进制数字,因此我们想将data中的每个元素用两个十六进制的数字表示就必须初始化一个是data长度两倍的char数组,这就是out对象的长度是[l << 1]的原因。

我们在源码汇中也可以看到这样的注释// two characters form the hex value.

紧接着,for循环。我们可以在脑海中创建这样一幅景象,两个并列的数组byte[] data和char[] out我们从data中取第一个元素,将其以二进制的数字表示出来,然后拆分高四位低四位,分别找到对应的两个十六进制的字符表示,然后再塞入char[]数组中,这就是这个for循环的功能!

0xF0 & data[i]根据“与运算”的逻辑规则,我们得知其目的是为了使得data[i]的低四位都变成0;然后>>>4无符号右移4位,取得高四位所表示的数值,我们可以换一种理解,“与”的目的是让低四位变成0,然后右移是为了去掉高四位后面的四个0,这样我们就拿到了高四位表示的值(我们已经知道二进制的四位数的取值范围就是0到15)。然后将这个高四位表示的值作为index找到对应的DIGITS_LOWER数组中的字符,并赋值给out[j],然后++两次,代表高位一次和低位一次,这样,我们就成功的完成了一组高四位低四位的拆分、替换、重组,然后只要循环data数组的长度就可以对每个byte元素进行相同的拆分重组操作了。

最后返回char[] out 。

这是一个非常简单实用的byte[]数组转化为String的小方法,API的开发者巧妙的利用'0'到'f'这十六个字符“代表” 0 到 15这十六个十六进制数,然后将byte元素逐一拆分并重组成一个新的char[]数组。

以上是本人经过实践之后对源码的分析和理解,喜欢的朋友记得点赞哦,作为一个工作仅两年的小菜鸟来说诚然是不小的鼓励,如果同行的朋友有什么问题和建议,还请不吝赐教!

2019-07-02 追加更新

这里需要注意一个问题,即byte的取值范围问题,原来之前的知识有漏洞,忽视了下面这句代码的重要性:

out[j++] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4];

这句代码的信息量很大,首先, >>> 是为了取byte元素的高四位,这个不难理解,但是为什么一定要先进行(0xF0 & data[i]) 运算?这个 & 运算是不是可有可无?

一开始我也认为是可有可无的,但实际上并不是!byte 变量的取值范围很小,是 [-128  ~  127],同样是 1000 0000,int类型所表示的是128, 而byte类型锁表示的数是 -128 ,因此,必须先将 byte 变量进行扩容转正,那么实现方法就是 & 0xF0,否则的话,如果 一个 byte类型的F0 ,表示的数代表 -16,再 >>> 4 的话,就会得到 -1 ,很明显不符合要求,因此& 0xF0 这句代码必不可少。

另外一个问题是 j++ ,++ 在后代表先取值,在加 1,那么out[j++] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4]; 就相当于下面这句代码:

out[j] = DIGITS_UPPER[(0xF0 & data[i]) >>> 4];
j++;

 总之,千万别小看这些细节,搞不明白还真容易翻船!不得不佩服这些写底层API “轮子”的大神,能把各种语法和知识用到极致!

如果老铁们有幸看到这篇文章,而且也玩头条的话,欢迎关注我的头条号,不得不说,以前写博客是两三天一更,已经感觉很累,现在头条号要日更,还要篇篇精品,真的非常累,希望大家多多关注!头条号搜索 “Java圣斗士” ,谢谢老铁了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559054.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring Boot————简介与Spring时代的承接

引言 最近&#xff0c;公司正在开发一个景区系统的项目&#xff0c;涉及到Spring Boot框架的使用&#xff0c;在此记录下Spring Boot框架应该知道的基础知识。 一、产生 SpringBoot是顺应现在微服务&#xff08;MicroServices&#xff09;理念而产生的一个微框架&#xff08…

计算机考试400,400作文:电脑考试

400作文&#xff1a;电脑考试今天下午第三节课是大家最爱的电脑课&#xff0c;第三节课的上课铃还没敲响&#xff0c;大家就早早来到电脑室门口&#xff0c;拍好整齐的队伍&#xff0c;等待电脑金老师来带领我们进电脑室。终于&#xff0c;金老师面带微笑从办公室走到了我们这边…

史上最容易理解的暴力递归和动态规划~~

史上最容易理解的暴力递归和动态规划~~介绍递归和动态规划暴力递归&#xff1a;1&#xff0c; 把问题转化为规模缩小了的同类问题的子问题2&#xff0c; 有明确的不需要继续进行递归的条件(base case)3&#xff0c; 有当得到了子问题的结果之后的决策过程 4&#xff0c; 不记录…

英雄联盟与人生奋斗的类比讨论

自从去年毕业之后就已经很少玩英雄联盟了&#xff0c;最近半年更是一次都没碰过这个游戏了。 更新还是异常的频繁&#xff0c;打斗还是异常的激烈&#xff0c;比赛还是异常的水&#xff08;S系列中国队的表现&#xff09;。 我今天并不是想追忆曾经的激情&#xff0c;而是想把…

如何最好手机硬件测试软件,手机硬件出现故障?简单几部教你自己动手检测! _手机资讯...

很多人在使用手机时&#xff0c;经常遇到例如屏幕触摸不准、距离感应器不反应、手机按键失灵等类似问题&#xff0c;有的情况是系统故障&#xff0c;但大多数是属于硬件故障&#xff0c;那如何判定呢&#xff1f;其实很多安卓手机自带的有硬件检测工具&#xff0c;下面就以小米…

String StringBuilder StringBuffer三者之间的区别~~~

String StringBuilder StringBuffer三者之间的区别~~~String是字符串常量&#xff0c;它是典型的immutable类&#xff0c;被声明final class&#xff0c;所有的属性都是final&#xff0c;由于它的不变性&#xff0c;类似拼接&#xff0c;剪裁字符串等操作&#xff0c;都会产生…

qq传输文件的软件测试点,超强新功能 QQ传文件夹测试版抢先试用

QQ传文件夹测试版试用(1)中关村在线软件事业部消息 腾讯体验中心今日(7月29日)发布了一个新的体验项目“QQ2009传文件夹测试版”。QQ的传文件功能&#xff0c;相信多数用户都使用过。在之前的版本中&#xff0c;很多用户反馈希望增加传文件夹的功能&#xff0c;方便多文件的传输…

String String.valueof() toString三者之间的区别~

String String.valueof() toString三者之间的区别~&#xff08;String &#xff09;强制类型转换&#xff0c;使用这种方法时&#xff0c;需要注意的是类型必须能转成String类型。因此最好用instanceof做个类型检查&#xff0c;以判断是否可以转换。否则容易抛出CalssCastExc…

SpringBoot学习——@Autowired自动注入报:could not be found问题的理解和解决方案

微服务应用程序中&#xff0c;我们会通过Java后台的方式发送http请求并调用其他注册在Spring Cloud Eureka server上的微服务&#xff0c;之前我们可能会手动封装一个Http发送请求类&#xff0c;然后通过其中的sendGet或者sendPost方法借由java IO的形式发送出去。 但是&#…

黑色玫瑰服务器延迟高,LOL:含金量最高的服务器,黑色玫瑰垫底,最后一个钻石起步!...

原标题&#xff1a;LOL&#xff1a;含金量最高的服务器&#xff0c;黑色玫瑰垫底&#xff0c;最后一个钻石起步&#xff01;黑色玫瑰。它是英雄联盟中非常特别的一个大区。这个大区是中间位置&#xff0c;电十&#xff0c;却是比电二高手还要多的地方。因为这个大区小姐姐特别的…

redis学习与入门~~~

redis学习与入门~~~ 一。 Redis 简介&#xff1a; 通常而言目前的数据库分类有几种&#xff0c;包括 SQL/NSQL,&#xff0c;关系数据库&#xff0c;键值数据库等等&#xff0c;分类的标准也不1&#xff0c;Redis本质上也是一种键值数据库的&#xff0c;但它在保持键值数据库简单…

Java网络编程————UDP实现ThinkPad S5网络唤醒

功能要求&#xff1a;通过Java程序实现ThinkPad S5 笔记本网络唤醒 必备知识&#xff1a; 一、定义&#xff1a;网络唤醒&#xff0c;通过局域网、互联网或通讯网络&#xff0c;以有线网卡的形式&#xff0c;向目标电脑发送魔法包(Magic Packet)&#xff0c;让电脑自动开机。…

FFmpeg在Ubuntu的安装以及教程~~~

FFmpeg在Ubuntu的安装以及教程~~~一、安装 可通过PPA进行安装sudo add-apt-repository ppa:kirillshkrogalev/ffmpeg-next sudo apt-get update sudo apt-get install ffmpeg 查看是否安装成功&#xff1a; ffmpeg -version二、相关概念比特率比特率&#xff0c;是一个决定音视…

Java学习指导————如何做到基础扎实

原文出处&#xff1a;《一篇文章教会你&#xff0c;如何做到招聘要求中的“要有扎实的Java基础”》 引言 不少同学总会产生这样的疑问&#xff1a; “请问&#xff0c;如何才叫基础扎实&#xff1f;” 答案是&#xff1a;“玩好JDK&#xff01;” JDK学习内容主要包含三部分…

奥特曼系列ol服务器名称带怪兽,《奥特曼系列ol》怪兽图鉴 怪兽阵容

《奥特曼系列ol》这款游戏中的怪兽图鉴也是很多玩家非常关注的问题之一哦&#xff0c;随着游戏的不断的更新&#xff0c;游戏也是加入了不少全新的玩法&#xff0c;一定让很多玩家觉得有些迷惑吧。下面小编为大家带来《奥特曼系列ol》怪兽图鉴以及怪兽阵容&#xff0c;希望大家…

继上一篇博客--javaweb通过接口来实现多个文件压缩和下载(包括单文件下载,多文件批量下载)

通过动态分配地址来提升javaweb文件下载接口的其兼容性和可扩展性&#xff1a; &#xff08;上篇博文地址&#xff1a;https://blog.csdn.net/weixin_37766296/article/details/80044000&#xff09;log4j.properties 文件&#xff1a; log4j.rootLogger debug,stdout,D,Elog4…

服务器主机启动不显示,服务器主机不启动怎么回事

服务器主机不启动怎么回事 内容精选换一换本文介绍了主机迁移服务SMS各特性版本的功能发布和对应的文档动态&#xff0c;新特性将在各个区域(Region)陆续发布&#xff0c;欢迎体验。源端服务器数据收集声明。源端服务器上安装和配置完迁移Agent后&#xff0c;迁移Agent会把源端…

Swagger自动接口文档生成框架————springboot整合swagger总结

swagger简介&#xff1a; swagger是一款开源的api接口文档生成工具。 Swagger的项目主页&#xff1a;https://swagger.io/ 目前比较流行的做法是在代码中加入swagger相关的注释&#xff0c;然后&#xff0c;利用小工具生成swagger.json或者swagger.yaml文件。 springboot…

申请 Let's Encrypt 数字证书,并安装cerbot快速上手教程~~

申请 Lets Encrypt 数字证书&#xff0c;并安装cerbot快速上手教程~~Let‘s Encrypt SSL证书介绍如今&#xff0c;越来越多的网站已经由HTTP迁移到HTTPS安全协议了。HTTPS不但能够避免网站内容在传输过程中被恶意篡改&#xff0c;切实保护访问者的权益&#xff0c;还能够让搜索…

Java常用设计模式————单例模式

单例模式简介 90%以上的设计模式都或多或少的应用了接口和抽象类&#xff0c;而单例比较特殊&#xff0c;并没有接口的应用。 单例Singleton指仅仅被实例化一次的类。通常被用来代表那些本质上唯一的系统组件。————《Effective Java》 数据库连接获取类的对象可以是单例的…