使用Java 将字节数组转成16进制的形式

概述

在很多场景下,需要进行分析字节数据,但是我们存起来的字节数据一般都是二进制的,这时候就需要我们将其转成16进制的方式方便分析。比如在做音视频的时候,需要看下我们传输的视频h264数据中是否有对应的I帧或者B帧等数据,做ASM插桩的时候,可以使用输出类结构的16进制辅助分析了解问题。测试投屏的时候尤其有用,比如说投屏到电视上后,发现没有画面,或者是画面很卡顿,这时候就需要对我们传输的视频数据做分析,所以我们将视频的数据转成16进制的形式,并且以一定的格式输出,可以很方便的帮助我们定位问题。本文主要介绍如何使用Java将字节数组格式化成16进制的格式并输出。

输出效果展示

在这里插入图片描述上图是以一个class字节码文件的16进制的格式输出,下面就介绍如何将我们的字节数组输出成16进制的格式

代码实现

首先我们定义一个类,用于生成一个class文件,作为我们格式化的对象。读者使用的时候可以是其他数据,只要是字节数组的方式提供就行了,这里仅仅作为演示

public class ASMDemoEntity {private int intNum = 10;private static final String staticString = "hello world";public void fun() {System.out.println("I am fun");}public int add(int a, int b) {return a + b;}public static void main(String[] args) {System.out.println("a+b = " + new ASMDemoEntity().add(1, 2));new ASMDemoEntity().fun();}
}

然后定义一个枚举类,定义我们格式化后的16进制数据的输出样式以及分隔符,如下所示:

public enum HexFormat {// 无分隔符分别展示0,8,16,32列FORMAT_HEX_0("", 0),FORMAT_HEX_8("", 8),FORMAT_HEX_16("", 16),FORMAT_HEX_32("", 32),// 带空格分隔符分别展示0,8,16,32列FORMAT_HEX_SPACE__0(" ", 0),FORMAT_HEX_SPACE_8(" ", 8),FORMAT_HEX_SPACE_16(" ", 16),FORMAT_HEX_SPACE_32(" ", 32);public final String separator; // 分隔符public final int column; // 展示几列HexFormat(String separator, int column) {this.separator = separator;this.column = column;}
}

如上所示:FORMAT_HEX_0就表示展示0列,无分隔符,用一行展示完所有的16进制数据,而FORMAT_HEX_SPACE_32 表示以一个空格做分隔符,展示32列,就如我们本文展示的效果图一样。
接着我们使用一个FileUtil类去读我们生成的.class文件:

public class FileUtil {public static String getFilePath(String relativePath){URL resource = FileUtil.class.getResource("/");String dir = resource == null? "" : resource.getPath();return dir + relativePath;}public static byte[] readBytes(String filePath){File file = new File(filePath);if(!file.exists()){throw new IllegalArgumentException(filePath + "not exist");}InputStream in = null;try {in = Files.newInputStream(file.toPath());in = new BufferedInputStream(in);ByteArrayOutputStream bao = new ByteArrayOutputStream();IOUtil.copy(in,bao);return bao.toByteArray();} catch (IOException e) {e.printStackTrace();}finally {IOUtil.closeIO(in);}return null;}
}

使用一个IOUtil类做复制字节数组和关闭IO流

public class IOUtil {private static final int EOF = -1;private static final int BUFFER_SIZE = 1024 * 4;public static long copy(final InputStream input,final OutputStream output) throws IOException {long count = 0;int n;byte[] buffer = new byte[BUFFER_SIZE];while (EOF != (n = input.read(buffer))) {output.write(buffer, 0, n);count += n;}return count;}public static void closeIO(final Closeable closeable) {if(closeable != null){try {closeable.close();} catch (IOException ignored) {}}}
}

最后使用格式化工具类将字节数组格式化成16进制的样式并按照指定的格式输出

public class HexUtil {public static String hexFormat(byte[] bytes,HexFormat format){String separator = format.separator;int column = format.column;return hexFormat(bytes,separator,column);}private static String hexFormat(byte[] bytes, String separator, int column) {if(bytes == null || bytes.length < 1) {return "";}StringBuilder sb = new StringBuilder();Formatter fm = new Formatter(sb);int length = bytes.length;for (int i = 0; i < length; i++) {int val = bytes[i] & 0xFF;fm.format("%02X",val);if(column > 0 && (i+1) % column == 0){fm.format("%n");}else{fm.format("%s",separator);}}return sb.toString();}
}

在上面代码中的代码是Formatter.format()方法,它的作用是格式化我们的字节数组,我们传入的格式中带有%…X…时表示输出16进制数据,具体的定义如下:
%X: 正常输出16进制数
%NX: 十六进制数,输出N位,如果本身大于N位,正常输出,比如format("%2X",val);表示输出2位16进制数,若本身大于2位,正常输出
%NBX: 十六进制数,输出N位,不足N位就补B,若本身大于N位,就正常输出,比如format("%02X",val);代表输出2位的16进制数,如果不足2位就补0,如果本身大于2位,就正常输出

演示将一个class文件的二进制数据转成16进制数据并格式化后输出:

public class HexFormatMain {public static void main(String[] args) {String relativePath = "org/example/entity/ASMDemoEntity.class";String filePath = FileUtil.getFilePath(relativePath);System.out.println("file path: " + filePath);byte[] bytes = FileUtil.readBytes(filePath);String hex = HexUtil.hexFormat(bytes, HexFormat.FORMAT_HEX_SPACE_32);System.out.println("class文件的16进制: ");System.out.println(hex);}
}

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

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

相关文章

07、SpringBoot 源码分析 - SpringApplication启动流程七

SpringBoot 源码分析 - SpringApplication启动流程七 初始化基本流程SpringApplication的prepareContext准备上下文postProcessApplicationContext处理applyInitializers初始化器初始化load SpringApplication的refreshContext刷新上下文refreshServletWebServerApplicationCon…

8.什么是HOOK

程序编译的本质是&#xff0c;首先计算机它只能看得懂机器码也就是只能看得懂数字&#xff0c;机器码学起来很费劲然后就创造了编译器这个东西&#xff0c;编译器它懂机器语言所以它可以跟机器沟通&#xff0c;而我们人可以跟编译器沟通&#xff0c;人跟编译器的语言就是各种各…

[Vulnhub]Vulnix 通过NFS挂载+SSH公钥免密登录权限提升

端口扫描 Server IP AddressPorts Open192.168.8.103TCP:22/tcp, 25/tcp, 79/tcp, 110/tcp, 111/tcp, 143/tcp, 512/tcp, 513/tcp, 514/tcp, 993/tcp, 995/tcp, 2049/tcp, 37522/tcp, 42172/tcp, 43219/tcp, 47279/tcp, 54227/tcp $ nmap -p- 192.168.8.103 -sV -sC --min-ra…

MyBatis系统学习 - 使用Mybatis完成查询单条,多条数据,模糊查询,动态设置表名,获取自增主键

上篇博客我们围绕Mybatis链接数据库进行了相关概述&#xff0c;并对Mybatis的配置文件进行详细的描述&#xff0c;本篇博客也是建立在上篇博客之上进行的&#xff0c;在上面博客搭建的框架基础上&#xff0c;我们对MyBatis实现简单的增删改查操作进行重点概述&#xff0c;在MyB…

P459 包装类Wrapper

包装类的分类 1&#xff09;针对八种基本数据类型相应的引用类型——包装类。 2&#xff09;有了类的特点&#xff0c;就可以调用类中的方法。 Boolean包装类 Character包装类 其余六种Number类型的包装类 包装类和基本数据类型的相互转换 public class Integer01 {publi…

解决文件夹打开出错问题:原因、数据恢复与预防措施

在我们日常使用电脑或移动设备时&#xff0c;有时会遇到一个非常棘手的问题——文件夹打开出错。这种错误可能会让您无法访问重要的文件和数据&#xff0c;给工作和生活带来极大的不便。本文将带您深入了解文件夹打开出错的原因&#xff0c;并提供有效的数据恢复方案&#xff0…

【网络协议】应用层协议--HTTP

文章目录 一、HTTP是什么&#xff1f;二、HTTP协议工作过程三、HTTP协议1. fiddler2. Fiddler抓包的原理3. 代理服务器是什么?4. HTTP协议格式1.1 请求1.2 响应 四、认识HTTP的请求1.认识HTTP请求的方法2.认识请求头&#xff08;header&#xff09;3.认识URL3.1 URL是什么&…

SparkSQL入门

1、SparkSQL是什么&#xff1f; 结论&#xff1a;SparkSQL 是一个即支持 SQL 又支持命令式数据处理的工具 2、SparkSQL 的适用场景&#xff1f; 结论&#xff1a;SparkSQL 适用于处理结构化数据的场景&#xff0c;而Spark 的 RDD 主要用于处理 非结构化数据 和 半结构化数据 …

掌握ASPICE标准:汽车软件测试工程师的专业发展路径

掌握ASPICE标准&#xff1a;汽车软件测试工程师的专业发展路径 文&#xff1a;领测老贺 随着新能源汽车在中国的蓬勃发展&#xff0c;智能驾驶技术的兴起&#xff0c;汽车测试工程师的角色变得愈发关键。这一变革带来了前所未有的挑战和机遇&#xff0c;要求测试工程师不仅要具…

解决git克隆项目出现fatal无法访问git clone https://github.com/lvgl/lvgl.git

Windows 11系统 报错 $ git clone https://github.com/lvgl/lvgl.git Cloning into lvgl... fatal: unable to access https://github.com/lvgl/lvgl.git/: Failed to connect to github.com port 443 after 21141 ms: Couldnt connect to server 解决方法 git运行这两段代码…

创新实训2024.05.26日志:落地基于硬盘的数据库服务

1. 需求任务列表 以下描述易学大模型软件的web应用的功能。 用户注册 用户邮箱&#xff0c;密码&#xff0c;验证码开启官方邮箱&#xff0c;用来发验证码&#xff08;QQ 网易都支持开启smtp协议&#xff0c;找教程&#xff0c;用邮箱不用手机号是为了省买发短信云服务的钱&a…

ASP+ACCESS客户管理信息系统

摘要 本文介绍了客户管理系统的实现方法。目的在于让大家共享学习和运用这一语言的体会和收获。本系统是Internet/Intranet环境下面向电子商务的客户管理&#xff0c;通过企业管理技术、电子商务和信息技术的高度集成&#xff0c;讨论了客户管理系统的系统构架、系统的工作…

栈和队列的基本见解

1.栈 1.1栈的基本概念和结构&#xff1a; 栈是一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出的原则。 压栈&#xff1a;栈的插入操作叫做进栈/压栈…

python 面对对象 类 魔法方法

魔法方法 一、__init__ 构造函数&#xff0c;可以理解为初始化 触发条件&#xff1a;在实例化的时候就会触发 class People():def __init__(self, name):print(init被执行)self.name namedef eat(self):print(f{self.name}要吃饭)a People(张三) a.eat() # in…

海外抖音TK自动挂机,手机全自动挂机,每天轻松搞2张

海外抖音TK自动挂机&#xff0c;手机全自动挂机&#xff0c;每天轻松搞2张 课程获取方式&#xff1a; https://zzmbk.com/

揭秘Markdown:轻松掌握基础语法,让你的写作更高效、优雅!

文章目录 前言1.标题1.1 使用 和 - 标记一级和二级标题1.2 使用 # 号标记 2.段落格式2.1 字体2.2 分割线2.3 删除线2.4 下划线2.5 脚注 3.列表3.1 无序列表3.2 有序列表3.3 列表嵌套 4.区块4.1 区块中使用列表4.2 列表中使用区块 5.代码代码区块 6.链接7.图片8.表格9.高级技巧…

mysql实战——XtraBackup二进制包安装

1、二进制包下载网站 Software Downloads - Percona 2、安装xtrabackup 解压安装包 tar xvf percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17.tar.gz -C /usr/local 进入目录 cd percona-xtrabackup-8.0.27-19-Linux-x86_64.glibc2.17/ 安装依赖 yum install perl-Dig…

2024.5.25期末测试总结

成绩&#xff1a; 配置&#xff1a; 可能与实际有些出入 题目&#xff1a; 第一题&#xff1a; 代码思路&#xff1a; 一道模拟题&#xff0c;按照公式计算出sumpow(2,i)&#xff0c;判断sum>H&#xff0c;输出 代码&#xff1a; #include<bits/stdc.h> using name…

Java—内部类

Java—内部类 一、内部类二、应用特点三、分类3.1、普通内部类&#xff1a;直接将一个类的定义放在另外一个类的类体中3.2、静态内部类3.3、局部内部类 一、内部类 一个类的定义出现在另外一个类&#xff0c;那么这个出现的类就叫内部类(Inner)。 内部类所在的类叫做外部类(Ou…

在线软件包管理

1.APT工作原理 APT&#xff08;Advanced Packaging Tool&#xff09;是Debian系列Linux操作系统中广泛使用的包管理工具&#xff0c;它为用户提供了从软件仓库搜索、安装、升级和卸载软件包的功能。其工作原理具体分析如下&#xff1a; 1. **集中式软件仓库机制**&#xff1a…