Introduction to HexFormat in Java 17 – Java中的HexFormat简介 17

最后修改: 2021年 11月 7日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

In Java, we usually write our own methods to handle conversions between bytes and hexadecimal strings. However, Java 17 introduces java.util.HexFormat, a utility class that enables the conversion of primitive types, byte arrays, or char arrays to a hex string and vice versa.

在Java中,我们通常自己编写方法来处理字节和十六进制字符串之间的转换。然而,Java 17引入了java.util.HexFormat,这是一个实用类,可以将原始类型、字节数组或char数组转换为十六进制字符串,反之亦然

In this tutorial, we’ll explore how to use HexFormat and demonstrate the functionality it provides.

在本教程中,我们将探讨如何使用HexFormat并演示其提供的功能。

2. Dealing with Hex Strings Before Java 17

2.在Java之前处理十六进制字符串 17

The hexadecimal numbering system uses a base of 16 to represent numbers. This means it consists of 16 symbols, usually the symbols 0-9 for values from 0 to 9, and A-F for values from 10 to 15.

十六进制计数系统使用16进制来表示数字。这意味着它由16个符号组成,通常用符号0-9表示0到9的数值,用A-F表示10到15的数值。

This is a popular choice for representing long binary values since it’s much easier to reason about compared to binary strings of 1s and 0s.

这是表示长二进制值的一个流行选择,因为与1和0的二进制字符串相比,它更容易推理。

When we need to convert between hexadecimal strings and byte arrays, developers typically write their own method using String.format() to do the work for them.

当我们需要在十六进制字符串和字节数组之间进行转换时,开发人员通常会使用String.format()编写自己的方法,为他们完成工作。

This is a simple and easy to understand implementation but tends to be inefficient:

这是一个简单易懂的实现方式,但往往效率不高。

public static String byteArrayToHex(byte[] a) {
    StringBuilder sb = new StringBuilder(a.length * 2);
    for (byte b: a) {
       sb.append(String.format("%02x", b));
    }
    return sb.toString();
}

Another popular solution is to use the Apache Commons Codec library, which contains a Hex utility class:

另一个流行的解决方案是使用Apache Commons Codec库,它包含一个Hex实用类。

String foo = "I am a string";
byte[] bytes = foo.getBytes();
Hex.encodeHexString(bytes);

One of our other tutorials explains different ways to manually perform this conversion.

我们的一个其他教程解释了手动执行这种转换的不同方法

3. HexFormat Usage in Java 17

3.HexFormat在Java中的应用 17

HexFormat can be found in the Java 17 standard library and can handle conversions between bytes and hexadecimal strings. It also supports several formatting options.

HexFormat可以在Java 17标准库中找到,它可以处理字节和十六进制字符串之间的转换。它还支持几个格式化选项。

3.1. Creating a HexFormat

3.1.创建一个HexFormat

How we create a new instance of HexFormat depends on whether we want delimiter support or not. HexFormat is thread-safe, so one instance can be used in multiple threads.

我们如何创建一个新的HexFormat,取决于我们是否需要分隔符支持HexFormat是线程安全的,所以一个实例可以在多个线程中使用。

HexFormat.of() is the most common use case, which we use when we don’t care for delimiter support:

HexFormat.of() 是最常见的使用情况,当我们不关心分隔符支持时,我们会使用它。

HexFormat hexFormat = HexFormat.of();

HexFormat.ofDelimiter(“:”) can be used for delimiter support, this example using a colon as the delimiter:

HexFormat.ofDelimiter(“:”) 可用于支持分隔符,本例使用冒号作为分隔符。

HexFormat hexFormat = HexFormat.ofDelimiter(":");

3.2. String Formatting

3.2.字符串格式化

HexFormat allows us to add prefix, suffix, and delimiter formatting options to existing HexFormat objects. We can use these to control the formatting of the String that is being parsed or produced.

HexFormat允许我们向现有的HexFormat对象添加前缀、后缀和分隔符格式化选项。我们可以使用这些选项来控制正在解析或生成的String的格式化。

Here’s an example of using all three together:

下面是一个三者结合使用的例子。

HexFormat hexFormat = HexFormat.of().withPrefix("[").withSuffix("]").withDelimiter(", ");
assertEquals("[48], [0c], [11]", hexFormat.formatHex(new byte[] {72, 12, 17}));

In this case, we’re creating the object using the simple of() method and then adding the delimiter using withDelimiter().

在这种情况下,我们使用简单的of()方法创建对象,然后使用withDelimiter()添加分隔符。

3.3. Bytes and Hexadecimal String Conversion

3.3.字节和十六进制字符串转换

Now that we’ve seen how to create a HexFormat instance, let’s go over how we can perform conversions.

现在我们已经看到了如何创建一个HexFormat实例,让我们来看看我们如何进行转换。

We’ll use the simple method of creating an instance:

我们将使用简单的方法来创建一个实例。

HexFormat hexFormat = HexFormat.of();

Next, let’s use this to convert a String to byte[]:

接下来,让我们用它来转换一个Stringbyte[]

byte[] hexBytes = hexFormat.parseHex("ABCDEF0123456789");
assertArrayEquals(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119 }, hexBytes);

And back again:

然后再回来。

String bytesAsString = hexFormat.formatHex(new byte[] { -85, -51, -17, 1, 35, 69, 103, -119});
assertEquals("ABCDEF0123456789", bytesAsString);

3.4. Primitive Type to Hexadecimal String Conversion

3.4.原始类型到十六进制字符串的转换

HexFormat also supports the conversion of primitive types to hexadecimal strings:

HexFormat还支持将原始类型转换为十六进制字符串。

String fromByte = hexFormat.toHexDigits((byte) 64);
assertEquals("40", fromByte);

String fromLong = hexFormat.toHexDigits(1234_5678_9012_3456L);
assertEquals("000462d53c8abac0", fromLong);

3.5. Uppercase and Lowercase Output

3.5.大写和小写输出

As the examples show, the default behavior of HexFormat is to produce a lowercase hexadecimal value. We can change this behavior by calling withUpperCase() when creating our HexFormat instance:

如例子所示,HexFormat的默认行为是产生一个小写的十六进制值。我们可以通过在创建HexFormat实例时调用withUpperCase()来改变这一行为

upperCaseHexFormat = HexFormat.of().withUpperCase();

Even though lowercase is the default behavior, a withLowerCase() method also exists. This is useful to make our code self-documenting and explicit for other developers.

尽管小写字母是默认行为,但也存在一个withLowerCase() 方法。这对于使我们的代码具有自我记录性并对其他开发者来说是很有用的。

4. Conclusion

4.总结

The introduction of HexFormat in Java 17 solves many issues that we traditionally face when performing conversions between bytes and hexadecimal strings.

Java 17中引入的HexFormat解决了我们传统上在进行字节和十六进制字符串之间的转换时所面临的许多问题。

We’ve been through the most common use cases in this article, but HexFormat also supports more niche functionality. For example, there are more conversion methods and the ability to manage the upper and lower half of a full byte.

我们在本文中已经介绍了最常见的用例,但HexFormat也支持更多的小众功能。例如,有更多的转换方法和管理一个完整字节的上半部分和下半部分的能力。

Official documentation for HexFormat is available in the Java 17 docs.

HexFormat的官方文档在Java 17 docs中提供。

As usual, the examples we presented in this article are over on GitHub.

像往常一样,我们在本文中介绍的例子是在GitHub上的