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

news2024/10/5 16:05:34

概述

在很多场景下,需要进行分析字节数据,但是我们存起来的字节数据一般都是二进制的,这时候就需要我们将其转成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.coloradmin.cn/o/1698355.html

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

相关文章

【java程序设计期末复习】chapter2 基本数据类型与数组

基本数据类型与数组 一&#xff0c;标识符和关键字 标识符 定义 用来标识类名、变量名、方法名、类型名、数组名、文件名的有效字符序列称为标识符&#xff0c;简单地说&#xff0c;标识符就是一个名字 。 性质 &#xff08;1&#xff09;标识符由字母、下划线、美元符号和…

集合竞价选股策略实战测试

2.3.2版本发布的集合竞价选股策略是网友吴PSYP提供的&#xff0c;团队按照策略实现的选股算法&#xff0c;最近半个月对策略进行的实战测试&#xff0c;从集合竞价选股开始&#xff0c;到股票收盘&#xff0c;收盘价格大于集合竞价价格&#xff0c;算作盈利&#xff0c;测试结果…

贪心-ACW803区间合并-XMUOJ力量碎片合并

题目 思路 附上几个参考链接 for(auto i : v)遍历容器元素_for auto 遍历-CSDN博客 C pair的基本用法总结&#xff08;整理&#xff09;_c pair用法-CSDN博客 使用 sort 实现自定义排序 - AcWing 话不多说&#xff0c;直接上代码 代码 /* ACW803区间合并-XMUOJ力量碎片合…

Redis-事务

简介 说到事务&#xff0c;一般都会第一时间的想到MySQL的事务。 在MySQL中事务的提出是为了解决解决原子性操作的&#xff0c;一组执行命令要么全部执行成功&#xff0c;要么执行失败进行回滚&#xff0c;一条也不执行。 在Redis中也有事务这个概念&#xff0c;但与MySQL相…

基于Pytorch框架的深度学习EfficientNet神经网络香蕉水果成熟度识别分类系统源码

第一步&#xff1a;准备数据 4种香蕉水果成熟度数据&#xff1a;overripe&#xff0c;ripe&#xff0c;rotten&#xff0c;unripe&#xff08;过熟、熟、烂、未成熟&#xff09;&#xff0c;总共有13474张图片&#xff0c;每个文件夹单独放一种成熟度数据 第二步&#xff1a;搭…

零基础小白可以做抖音电商吗?小白做电商难度大吗?一篇全解!

大家好&#xff0c;我是电商花花 在直播电商的热度越来越多&#xff0c;更多普通的创业者都对抖音小店电商有了想法&#xff0c;因为很多普通 人都通过抖音小店开店卖货赚到了钱&#xff0c;让更多人对抖店电商产生了兴趣。 于是做抖音小店无货源&#xff0c;开店卖货赚钱成为…

【软件推荐】obsidian设置

【软件推荐】obsidian设置 初始化 附件相对路径设置 打开obsidian 设置-文件与链接&#xff0c;找到下图的这几个设置。设置为如图所示。 插件推荐 实时渲染 你可能会想&#xff0c;obsidian的使用体验没有typora好呀&#xff01; typora可以实时渲染&#xff0c;obsid…

用c++用4个凸函数(觉得啥好用用啥)去测试adam,rmsprop,adagrad算法的性能(谁先找到最优点)

为了测试 Adam、RMSProp 和 Adagrad 算法的性能&#xff0c;你可以使用四个凸函数进行实验。以下是一些常用的凸函数示例&#xff1a; Rosenbrock 函数&#xff1a; Booth 函数&#xff1a; Himmelblau 函数&#xff1a; Beale 函数&#xff1a; 你可以选择其中一个或多…

光线追踪技术在AI去衣中的革命性角色

引言&#xff1a; 随着人工智能和计算机图形学的飞速发展&#xff0c;AI去衣技术已经从理论走向实践&#xff0c;为影视制作、虚拟现实、在线试衣等领域提供了强大的技术支持。在这一过程中&#xff0c;光线追踪技术以其卓越的渲染能力和逼真的光影效果&#xff0c;成为AI去衣领…

C++开发面试常问总结

一些面试总结 TCP粘包了解吗&#xff1f;解决办法&#xff1f;讲一下乐观锁悲观锁git中 git pull和git fetch的区别1.虚函数实现机制&#xff1a;2.进程和线程的区别&#xff1a;3.TCP三次握手、四次挥手&#xff1a;4.HTTP状态码&#xff0c;报头&#xff1a;5.智能指针&#…

MySql基础(一)--最详细基础入门,看完就懂啦(辛苦整理,想要宝宝的赞和关注嘻嘻)

前言 希望你向太阳一样&#xff0c;有起有落&#xff0c;不失光彩~ 一、数据库概述 1. 什么是数据库 数据库就是存储数据的仓库&#xff0c;其本质是一个文件系统&#xff0c;数据按照特定的格式将数据存储起来&#xff0c;用户可以对数据库中的数据进行增加&#xff0c;修改&…

【Django项目】 音乐网站spotify复刻

代码&#xff1a;https://github.com/tomitokko/spotify-clone 注&#xff1a;该项目不是自己提供mp3文件&#xff0c;而是使用spotify 的api接口获取。

奇舞周刊第529期:万字长文入门前端全球化

周五快乐&#xff08;图片由midjourney生成&#xff09; 奇舞推荐 ■ ■ ■ 万字长文入门前端全球化 目前国内企业正积极开拓国际市场&#xff0c;国际化已成为重要的发展方向&#xff0c;因此产品设计和开发更需考虑国际化。本文介绍了语言标识、文字阅读顺序等诸多知识。然后…

【编译原理复习笔记】中间语言

中间语言 中间语言的特点和作用 &#xff08;1&#xff09;独立于机器 &#xff08;2&#xff09;复杂性介于源语言和目标语言之间 中间语言可以使编译程序的结构在逻辑上更为简单明确 常用的中间语言 后缀式 图表示&#xff1a;抽象语法树&#xff0c;有向无环图 三地址代…

淘宝x5sec

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01;wx a15018601872 本文章未…

LeetCode 264 —— 丑数 II

阅读目录 1. 题目2. 解题思路3. 代码实现 1. 题目 2. 解题思路 第一个丑数是 1 1 1&#xff0c;由于丑数的质因子只包含 2 、 3 、 5 2、3、5 2、3、5&#xff0c;所以后面的丑数肯定是前面的丑数分别乘以 2 、 3 、 5 2、3、5 2、3、5 后得到的数字。 这样&#xff0c;我…

类的内存对齐位段位图布隆过滤器哈希切割一致性哈希

文章目录 一、类的内存对齐1.1规则1.2原因 二、位段2.1介绍2.2内存分配问题2.3跨平台问题2.4使用的注意事项 三、位图的应用3.1 给40亿个不重复的无符号整数&#xff0c;找给定的一个数。&#xff08;int的范围可以到达42亿多&#xff09;3.2 给定100亿个整数&#xff0c;设计算…

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal

openEuler 22.03 LTS SP3源码编译部署OpenStack-Caracal 说明机器详情安装操作系统注意事项基础准备Controller节点 && Compute节点 && Block节点关闭防火墙关闭selinux设置静态IP更新安装前准备Controller节点 && Compute节点 && Block节点设…

auto关键字(C++11)

auto关键字&#xff08;C11&#xff09; 文章目录 auto关键字&#xff08;C11&#xff09;前言一、auto使用规则二、auto不适用的场景三、auto推荐适用的场景总结 前言 在C11中&#xff0c;auto关键字能够自动推导出变量的实际类型&#xff0c;可以帮助我们写出更加简洁、现代…

开发公众号自定义菜单之创建菜单

文章目录 申请测试账号换取Token接口测试提交自定义菜单查看效果校验菜单配置清空菜单配置结束语 申请测试账号 https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?actionshowinfo&tsandbox/index 或 得到appid和secret 换取Token 使用appid和secret换取token令牌…