当前位置:首页 > 文章列表 > 文章 > java教程 > Java HexFormat 怎样把字节数组转换为可读十六进制

Java HexFormat 怎样把字节数组转换为可读十六进制

来源:17golang原创 2026-11-04 17:02:18 0浏览 收藏

在日志、协议调试或指纹展示中,byte[] 直接打印出来通常不适合阅读。Java 17 引入的 HexFormat 可以把字节数组转换成连续或带分隔符的十六进制文本,也能按同一格式解析回来。关键是:数组格式化用 formatHex,单个数值用 toHexDigits,二者的分隔符和前后缀规则不同。

官方 API 文档:https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/HexFormat.html

想得到可读结果,先用 HexFormat.ofDelimiter(":").withUpperCase() 构造格式,再调用 formatHex(bytes);需要回到字节数组时,必须用同一组 delimiter、prefix 和 suffix 调用 parseHex。

本文要点:①数组格式化与单值转换分开选 API;②配置对象是不可变副本,可以安全复用;③解析是严格格式匹配,不是“尽量猜测”。

先分清 HexFormat 的两种工作模式

HexFormat 同时覆盖“字节数组”和“primitive 单值”两类任务。字节数组使用 formatHex 或 parseHex,会处理每个字节的两位十六进制字符,以及可选的分隔符、前缀和后缀。单个 byte、int 或 long 使用 toHexDigits,它只关心大小写和固定宽度,不会套用数组格式的 delimiter。

因此,协议字段、指纹和日志行优先建立一个数组格式;需要把一个整数变成固定宽度十六进制时,才直接使用静态转换方法。不要因为方法名相近,就期待 toHexDigits(255) 自动输出数组格式或前缀。

用 formatHex 输出字节数组

最小配置是 HexFormat.of(),输出小写、无分隔符文本。要让日志中的字节边界更明显,可以使用 ofDelimiter,再通过 withUpperCase、withPrefix 或 withSuffix 返回新的格式对象:

import java.util.HexFormat;

public class HexFormatDemo {
    public static void main(String[] args) {
        // 用冒号分隔并使用大写,适合展示指纹或报文摘要。
        HexFormat fingerprint = HexFormat.ofDelimiter(":")
                .withUpperCase();
        byte[] bytes = {0x00, 0x01, 0x2a, (byte) 0xff};

        // formatHex 会为每个字节生成两位十六进制字符。
        String text = fingerprint.formatHex(bytes);
        System.out.println(text); // 00:01:2A:FF
    }
}

如果团队约定每个值带 #,可以继续调用 withPrefix("#")。这些 withXXX 方法返回副本,原来的 fingerprint 不会被修改,所以可以把格式对象定义为共享常量或注入到多个服务中。

HexFormat formatHex 将 byte 数组转换为带分隔符十六进制文本的静态说明图
图1:HexFormat.formatHex 的静态说明图,展示数组、格式配置与文本结果的关系。

用 parseHex 做严格往返

解析时不要只看字符串“像不像十六进制”。parseHex 会按照当前格式检查每个字节的前缀、两位十六进制字符、后缀和字节之间的分隔符;字符非法、分隔符缺失或前后缀不匹配时会抛出 IllegalArgumentException。最稳妥的做法是让产生文本和消费文本的两端共享同一个格式定义:

import java.util.Arrays;
import java.util.HexFormat;

public class HexRoundTrip {
    public static void main(String[] args) {
        // 解析规则必须与生成端保持一致:冒号分隔、每项带 #、使用小写。
        HexFormat format = HexFormat.ofDelimiter(":")
                .withPrefix("#")
                .withLowerCase();
        byte[] original = {0x10, 0x2a, (byte) 0xf0};
        String encoded = format.formatHex(original);

        try {
            // parseHex 只接受完全符合上述格式的文本。
            byte[] decoded = format.parseHex(encoded);
            System.out.println(Arrays.equals(original, decoded)); // true
        } catch (IllegalArgumentException ex) {
            // 把格式错误与业务层的校验失败分开记录。
            System.err.println("十六进制格式无效:" + ex.getMessage());
        }
    }
}

这个例子中,#10:#2a:#f0 可以成功解析;若改成 #10-#2a-#f0,分隔符不符就会失败。解析方法不负责替你删除空格、猜测分隔符或修复半个字节,因此外部输入要先明确协议规则。

HexFormat parseHex 合法往返与非法输入边界的静态说明图
图2:HexFormat.parseHex 的静态边界说明图,展示合法往返与非法输入的分流。

按规模和边界选择 API

小型日志可以直接调用 formatHex(byte[])。如果只需要数组的一段,使用带 fromIndex 和 toIndex 的重载,注意右端点是排他的,越界会抛出 IndexOutOfBoundsException。对于大数组或连续输出,formatHex(Appendable, byte[]) 可以写入 StringBuilder、Writer 等目标,减少一次完整中间字符串的压力。

还要记住三个边界:所有相关参数默认不能为 null;空数组格式化结果为空字符串;HexFormat 是不可变且线程安全的值类,比较配置应使用 equals,不要用 == 判断两个实例是否相同。

常见问题

为什么 toHexDigits 没有输出冒号或前缀?因为它服务于单个 primitive 的固定宽度转换,只读取大小写设置;delimiter、prefix 和 suffix 只参与数组格式化与解析。

解析时能不能接受大小写混用?十六进制字符本身按大小写不敏感解析,但 delimiter、prefix、suffix 以及它们出现的位置仍必须符合当前格式。若输入来自用户或外部协议,应先定义是否允许空白和其他包装字符,而不是依赖 parseHex 猜测。

把 HexFormat 当成“格式契约”而不只是转换工具,最容易维护:生产端固定配置,消费端复用同一配置;展示需求用 formatHex,单值需求用 toHexDigits,非法输入则在 parseHex 边界显式处理。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Java StringTemplate怎样安全拼接结构化文本Java StringTemplate怎样安全拼接结构化文本
上一篇
Java StringTemplate怎样安全拼接结构化文本
Java Foreign Function API怎样管理 Arena 中的本地内存
下一篇
Java Foreign Function API怎样管理 Arena 中的本地内存
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    883次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    880次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    965次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    947次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    775次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码