使用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);
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

01JAVA基础

目录 1.基础语法 1.1 注释 1.2 关键字 1.3 常量 1.4 数据类型 1.5 变量 1.6 标识符 1.7 类型转换 2.算数运算符和分支语句 2.1 算数运算符 1.常规运算符 2.赋值运算符 3.自增自减 4.关系运算符 5.逻辑运算符 6.三元运算符 2.2 数据输入(Scanner) 2.3 分支判断…

自定义类型:结构体详解

1.结构体 1.1 结构的基础知识 结构是一些值的集合&#xff0c;这些值称为成员变量。一个整型数组&#xff0c;它的每个数组元素只能是整型&#xff0c;字符型的数组它的每个元素只能是字符型。但是结构体的每个成员可以是各种不同类型的变量。 1.2结构的声明 //声明 struct t…

【java程序设计期末复习】chapter1 java入门

java入门 java的特点 &#xff08;1&#xff09;简单 Java要比C简单&#xff0c;C中许多容易混淆的概念&#xff0c;或者被Java弃之不用了&#xff0c;或者以一种更清楚更容易理解的方式实现 &#xff08;2&#xff09;面向对象 Java是面向对象的编程语言 &#xff08;3&…

【数据结构(邓俊辉)学习笔记】二叉树02——遍历

文章目录 0.概述1. 先序遍历1.1 递归版1.1.1 实现1.1.2 时间复杂度1.1.3 问题 1.2 迭代版11.3 迭代版21.3.1 思路1.3.2 实现1.3.3 实例 2. 中序遍历2.1 递归形式2.2 迭代形式2.2.1 观察2.2.2 思路&#xff08;抽象总结&#xff09;2.2.3 构思 实现2.2.4 分摊分析 3. 后序遍历3…

world machine学习笔记(4)

选择设备&#xff1a; select acpect&#xff1a; heading&#xff1a;太阳的方向 elevation&#xff1a;太阳的高度 select colour&#xff1a;选择颜色 select convexity&#xff1a;选择突起&#xff08;曲率&#xff09; select height&#xff1a;选择高度 falloff&a…

neo4j开放远程连接

注&#xff1a;本博客所用neo4j版本为社区5.12版 第一步&#xff1a;修改neo4j配置文件 首先找到neo4j的安装位置&#xff0c;点击进入conf文件夹&#xff0c;随后点击neo4j.conf文件&#xff0c;在“Network connector configuration”下面的单元中找到server.default_liste…

Android:使用Kotlin搭建MVVM架构模式

一、简介Android MVVM架构模式 MVVM全称&#xff1a;Model、View、ViewModel&#xff1b; Model&#xff1a;负责数据的请求、解析、过滤等数据层操作&#xff0c;其中Repository: 提供数据的 API&#xff08;从本地或者网络&#xff09;。View&#xff1a;负责视图部分展示Vie…

【热门话题】Debian常用命令指南

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Debian常用命令指南引言1. 文件与目录操作lscdmkdirrmcpmv 2. 包管理aptdpkg 3.…

kubenetes中K8S的命名空间状态异常强制删除Terminating的ns

查看ns状态为异常&#xff1a; 查看ns为monitoring的状态为Termingating状态 使用方法一&#xff1a; kubectl delete ns monitoring --force --grace-period0 使用方法二&#xff1a; kubectl get ns monitoring -o json > monitoring.json 修改删除文件中的"kubern…

BUUCTF-Misc24

从娃娃抓起1 1.打开附件 是两个文本文件 2.电报码 电报码在线翻译网站&#xff1a;https://usetoolbar.com/convert/cccn.html 3.汉字五笔编码 汉字五笔编码在线网站查询&#xff1a;https://www.qqxiuzi.cn/bianma/wubi.php 4.转化为MD5值 将文字保存到文本文档 用winR输入…

PCIe总线-事物层之TLP请求和完成报文格式介绍(六)

1.概述 TLP报文按照类型&#xff0c;可以大致分为4中类型&#xff0c;分别是IO请求报文、存储器请求报文、配置请求报文、完成报文和消息请求报文。IO请求报文可分为IO读请求&#xff08;不携带数据&#xff09;和IO写请求&#xff08;携带数据&#xff09;。存储器请求报文可…

第 33 次CCF认证

1. 词频统计 题目描述 样例输入 代码 #include <bits/stdc.h>using namespace std;int main() {int n,m;cin>>n>>m;vector<int> ans1(m,0),ans2(m,0);while (n --) {int t;cin>>t;vector<int> vis(m1,0);for (int i 1;i < t;i ) {i…

【Qt】深入探索Qt窗口与对话框:从创建到管理:QDockWidget(浮动窗口)、QDialog(对话框)

文章目录 前言&#xff1a;1. 浮动窗口2. 对话框介绍2.1. 示例&#xff1a;主窗口中&#xff0c;通过点击按钮&#xff0c;弹出一个新的对话框。2.2. 创建自定义对话框2.2.1. 纯代码的方式2.2.2. 图形化界面的方式 3. 模态对话框 和 非模态对话框4. Qt 内置对话框4.1. 消息对话…

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

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

【软件设计师】先导

一、考试科目&#xff1a; 上午&#xff1a;计算机与软件工程知识&#xff0c;考试时间150min&#xff0c;75空单选题&#xff08;不一定一题一空&#xff09; 下午&#xff1a;软件设计&#xff0c;考试时间150分钟&#xff0c;问答题&#xff0c;6道只做5大题&#xff08;前四…

Nginx 的原理解析 worker 配置及相关问题 -细节狂魔

文章目录 前言Nginx 的最基本的执行过程&#xff08;master & worker&#xff09;worker 是如何进行工作的 一个 master 和 多个 woker 有哪些好处1、可以使用 nginx 热部署2、节省资源 && worker 进程之间互不影响 && nginx 服务不会中断 woker 设置多少才…

简单美观易上手的 Docker Compose 可视化管理器 Dockge

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 Dockge 是 Uptime Kuma 作者的新作品&#xff0c;因此 UI 风格与 Uptime Kuma 基本一致&#xff0c;如果你正在使用 Uptime Kuma 的话&#xff0c;那么 Dockge 的 UI 设计应该也不会让你失望。Dockge 主打…

java人口老龄化社区服务与管理平台源码(springboot+vue+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的人口老龄化社区服务与管理平台。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 人口老龄化…

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

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