使用 HexFormat 来格式化和解析十六进制字符串

开发 前端
本文介绍了如何使用 JDK 17 新增的 HexFormat​ 工具类来格式化和解析十六进制字符串,通过 HexFormat 工具类还可以轻松地设置分隔符,字母大小写以及前缀和后缀。

十六进制(Hexadecimal)是一种数制系统,它使用 16 个数字来表示数值,分别是 0 到 9 和 A 到 F。

十六进制经常用于表示字节数据。在十六进制表示中,一个字节可以用两个十六进制数字表示。例如,字节的取值范围是 0 到 255,可以用 00 到 FF 来表示。其中,00 表示二进制的 00000000,FF 表示二进制的 11111111。这在 Socket 通信协议的定义中很常见。

简单来说,对于一些较短的二进制数据,可以把它序列化为十六进制字符串,其中每 2 个字符,表示一个字节。同样,也可以把十六进制的字符串解析为字节数组。最常见的场景就是把 Hash 计算的结果表示为十六进制字符串。

通常我们可以选择使用第三方的 commons-codec 库来实现格式化和解析十六进制字符串。可能是这个功能需求太常见,于是从JDK 17 开始,标准库中提供了一个 HexFormat 工具类,用于格式化和解析十六进制字符串。

简单地编码和解码

简单地把字节数组编码为十六进制字符串,以及把十六进制字符串解析为字节数组。

package cn.springdoc.demo.test;

import java.util.HexFormat;

public class Main {

    public static void main(String[] args) throws Exception {
        
        HexFormat format = HexFormat.of();
        
        String hex = format.formatHex("hello springdoc.cn".getBytes());
        System.out.println("Hex=" + hex);
        
        byte[] bytes = format.parseHex(hex);
        System.out.println("bytes=" + new String(bytes));
    }
}

首先,通过 of 静态方法创建 HexFormat 实例对象。然后调用 formatHex 方法来把字节数组格式化十六进制字符串。最后再调用 parseHex 方法把十六进制字符串解析为字节数组。

parseHex 和 parseHex 都有一些重载方法,可以指定字符串或者字节数组的区间:

  • String formatHex(byte[] bytes)
  • String formatHex(byte[] bytes, int fromIndex, int toIndex)
  • <A extends Appendable> A formatHex(A out, byte[] bytes)
  • <A extends Appendable> A formatHex(A out, byte[] bytes, int fromIndex, int toIndex)
  • byte[] parseHex(CharSequence string)
  • byte[] parseHex(CharSequence string, int fromIndex, int toIndex)
  • byte[] parseHex(char[] chars, int fromIndex, int toIndex)

执行方法,输出如下:

Hex=68656c6c6f20737072696e67646f632e636e
bytes=hello springdoc.cn

分隔符

在一些场景中,给十六进制字符串中每一个字节之间添加一个分隔符可读性会更好。

例如:68:65:6c:6c:6f:20:73:70:72:69:6e:67:64:6f:63:2e:63:6e。

// 通过 ofDelimiter 方法创建HexFormat,指定分隔符
HexFormat format = HexFormat.ofDelimiter(":");

String hex = format.formatHex("hello springdoc.cn".getBytes());
System.out.println("Hex=" + hex);

byte[] bytes = format.parseHex(hex);
System.out.println("bytes=" + new String(bytes));

// 获取分隔符
String delimiter = format.delimiter();
System.out.println("分隔符=" + delimiter);

只需要通过 ofDelimiter 静态方法,指定分隔符来创建 HexFormat 实例即可,同时也可以通过 delimiter 方法来获取设置的分隔符。

输出如下,每个字节(两个字符)之间都添加了指定的分隔符:

Hex=68:65:6c:6c:6f:20:73:70:72:69:6e:67:64:6f:63:2e:63:6e
bytes=hello springdoc.cn
分隔符=:

前缀和后缀

也可以给每个字节,即每两个十六进制字符串设置前缀和后缀。

HexFormat format = HexFormat.ofDelimiter(":")
        .withPrefix("[")    // 设置前缀
        .withSuffix("]")    // 设置后缀
        ;

String hex = format.formatHex("hello springdoc.cn".getBytes());
System.out.println("Hex=" + hex);

byte[] bytes = format.parseHex(hex);
System.out.println("bytes=" + new String(bytes));

System.out.println("前缀=" + format.prefix() + ", 后缀=" + format.suffix());

通过 withPrefix 和 withSuffix 方法来设置前缀和后缀。注意 HexFormat 是不可变的对象(类似于 String),所以任何修改都会返回一个新的 HexFormat 对象。

输出如下:

Hex=[68]:[65]:[6c]:[6c]:[6f]:[20]:[73]:[70]:[72]:[69]:[6e]:[67]:[64]:[6f]:[63]:[2e]:[63]:[6e]
bytes=hello springdoc.cn
前缀=[, 后缀=]

大小写

十六进制中有 A - F 字母,也可以设置字母的大小写。

HexFormat format = HexFormat.of()
    //  .withLowerCase()    // 字母小写,默认
        .withUpperCase()    // 字母大写
        ;

String hex = format.formatHex("hello springdoc.cn".getBytes());
System.out.println("Hex=" + hex);

byte[] bytes = format.parseHex(hex);
System.out.println("bytes=" + new String(bytes));

System.out.println("大写=" + format.isUpperCase());

通过 withLowerCase(默认)和 withUpperCase 方法来设置十六进制字符串中字母的大小写,通过 isUpperCase 方法来获取是否开启了大写。

输出如下:

Hex=68656C6C6F20737072696E67646F632E636E
bytes=hello springdoc.cn
大写=true

实际案例

最后来看一个实际案例,把 SHA256 哈希值编码为十六进制字符串:

package cn.springdoc.demo.test;

import java.security.MessageDigest;
import java.util.HexFormat;

public class Main {

    public static void main(String[] args) throws Exception {

        // 创建 SHA256 MessageDigest
        MessageDigest digest = MessageDigest.getInstance("SHA256");
        
        // 计算字符串 "123456" 的哈希值
        byte[] sha256 = digest.digest("123456".getBytes());
        
        // 把哈希结果编码为十六进制字符串
        String sha256Hex = HexFormat.of().withUpperCase().formatHex(sha256);
        
        System.out.println(sha256Hex);
    }
    }

输出如下:

8D969EEF6ECAD3C29A3A629280E686CF0C3F5D5A86AFF3CA12020C923ADC6C92

总结

本文介绍了如何使用 JDK 17 新增的 HexFormat 工具类来格式化和解析十六进制字符串,通过 HexFormat 工具类还可以轻松地设置分隔符,字母大小写以及前缀和后缀。

责任编辑:武晓燕 来源: SpringBoot中文站
相关推荐

2010-02-01 16:46:07

C++格式化字符串

2013-07-25 15:01:47

iOS开发学习十六进制和字符串转换

2021-06-09 07:55:18

Python格式化字符串

2009-11-26 18:36:52

PHP函数sprint

2009-09-02 15:56:49

C#格式化字符串

2009-09-03 18:05:04

ASP.NET字符串格

2022-05-09 14:04:27

Python字符串格式化输出

2020-06-28 08:26:41

Python开发工具

2017-01-16 16:33:06

Python 字符串漏洞

2009-09-03 18:45:06

GridView格式化

2020-09-02 07:19:41

printf 格式化输出Unix

2024-03-06 08:41:14

Python字符串格式化工具

2024-02-22 09:46:04

C++字符串格式化开发

2024-01-02 08:43:48

qs工具库格式化

2022-03-28 10:56:11

Python字符串格式化

2010-08-03 10:46:41

Flex代码格式化

2009-08-28 10:55:16

C#实现转换十六进制

2024-02-26 08:00:00

Pythonformat()字符串

2016-10-17 09:07:11

漏洞字符串EIP劫持

2010-01-07 17:58:49

JSON数值
点赞
收藏

51CTO技术栈公众号