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

 更新时间:2024年05月27日 08:50:52   作者:职场007  
在很多场景下,需要进行分析字节数据,但是我们存起来的字节数据一般都是二进制的,这时候就需要我们将其转成16进制的方式方便分析,本文主要介绍如何使用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);
    }
}

到此这篇关于使用Java将字节数组转成16进制形式的代码实现的文章就介绍到这了,更多相关Java字节数组转16进制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring使用Filter过滤器对Response返回值进行修改的方法

    spring使用Filter过滤器对Response返回值进行修改的方法

    这篇文章主要介绍了spring使用Filter过滤器对Response返回值进行修改,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-09-09
  • Scala常用List列表操作方法示例

    Scala常用List列表操作方法示例

    这篇文章主要介绍了Scala常用List列表操作方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-06-06
  • Java Comparator比较器实例解析

    Java Comparator比较器实例解析

    这篇文章主要介绍了Java Comparator比较器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Spring整合Mybatis框架方法剖析

    Spring整合Mybatis框架方法剖析

    这篇文章主要为大家介绍了Spring整合Mybatis框架方法剖析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07
  • Spring Boot支持HTTPS步骤详解

    Spring Boot支持HTTPS步骤详解

    这篇文章主要介绍了Spring Boot支持HTTPS步骤详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • JavaCV调用百度AI实现人脸检测方法详解

    JavaCV调用百度AI实现人脸检测方法详解

    在检测人脸数量、位置、性别、口罩等场景时,可以考虑使用百度开放平台提供的web接口,一个web请求就能完成检测得到结果。本文就为大家介绍JavaCV如何调用百度AI实现最简单的人脸检测,需要的可以参考一下
    2022-01-01
  • Java Socket实现文件传输示例代码

    Java Socket实现文件传输示例代码

    这篇文章主要介绍了Java Socket实现文件传输示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Java中避免过多if-else的几种方法

    Java中避免过多if-else的几种方法

    这篇文章主要介绍了Java中避免过多if-else的几种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • springboot中Controller中postman遇到的传参问题及解决

    springboot中Controller中postman遇到的传参问题及解决

    这篇文章主要介绍了springboot中Controller中postman遇到的传参问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • Java设计模式之状态模式(State模式)介绍

    Java设计模式之状态模式(State模式)介绍

    这篇文章主要介绍了Java设计模式之状态模式(State模式)介绍,本文讲解了何时使用状态模式、如何使用状态模式等内容,需要的朋友可以参考下
    2015-03-03

最新评论