Перейти к основному содержимому

Введение в HexFormat в Java 17

· 4 мин. чтения

1. Введение

В Java мы обычно пишем собственные методы для обработки преобразований между байтами и шестнадцатеричными строками. Однако в Java 17 представлен java.util.HexFormat , служебный класс, который позволяет преобразовывать примитивные типы, массивы байтов или массивы символов в шестнадцатеричную строку и наоборот .

В этом руководстве мы рассмотрим, как использовать HexFormat и продемонстрируем предоставляемые им функции.

2. Работа с шестнадцатеричными строками до Java 17

Шестнадцатеричная система счисления использует основание 16 для представления чисел. Это означает, что он состоит из 16 символов, обычно это символы 0-9 для значений от 0 до 9 и AF для значений от 10 до 15.

Это популярный выбор для представления длинных двоичных значений, поскольку его гораздо проще рассуждать по сравнению с двоичными строками из 1 и 0.

Когда нам нужно преобразовать между шестнадцатеричными строками и массивами байтов, разработчики обычно пишут свой собственный метод, используя String.format() , чтобы сделать работу за них.

Это простая и понятная реализация, но она имеет тенденцию быть неэффективной:

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();
}

Другим популярным решением является использование библиотеки кодеков Apache Commons , которая содержит служебный класс Hex :

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

В одном из наших других руководств объясняются различные способы ручного выполнения этого преобразования .

3. Использование HexFormat в Java 17

HexFormat можно найти в стандартной библиотеке Java 17, и он может обрабатывать преобразования между байтами и шестнадцатеричными строками . Он также поддерживает несколько вариантов форматирования.

3.1. Создание шестнадцатеричного формата

То, как мы создадим новый экземпляр HexFormat , зависит от того, нужна ли нам поддержка разделителей или нет . HexFormat является потокобезопасным, поэтому один экземпляр можно использовать в нескольких потоках.

HexFormat.of() является наиболее распространенным вариантом использования, который мы используем, когда нам не нужна поддержка разделителей:

HexFormat hexFormat = HexFormat.of();

HexFormat.ofDelimiter(“:”) можно использовать для поддержки разделителей, в этом примере в качестве разделителя используется двоеточие:

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

3.2. Форматирование строк

HexFormat позволяет нам добавлять параметры форматирования префикса, суффикса и разделителя к существующим объектам HexFormat . Мы можем использовать их для управления форматированием строки , которая анализируется или создается.

Вот пример использования всех трех вместе:

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

В этом случае мы создаем объект, используя простой метод of() , а затем добавляем разделитель, используя withDelimiter().

3.3. Преобразование байтов и шестнадцатеричных строк

Теперь, когда мы увидели, как создать экземпляр HexFormat , давайте рассмотрим, как мы можем выполнять преобразования.

Мы будем использовать простой метод создания экземпляра:

HexFormat hexFormat = HexFormat.of();

Далее воспользуемся этим для преобразования String в byte[] :

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

И снова:

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

3.4. Преобразование примитивного типа в шестнадцатеричную строку

HexFormat также поддерживает преобразование примитивных типов в шестнадцатеричные строки:

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

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

3.5. Вывод в верхнем и нижнем регистре

Как показывают примеры, HexFormat по умолчанию выдает шестнадцатеричное значение в нижнем регистре. Мы можем изменить это поведение, вызвав withUpperCase() при создании нашего экземпляра HexFormat :

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

Несмотря на то, что нижний регистр является поведением по умолчанию, также существует метод withLowerCase() . Это полезно, чтобы сделать наш код самодокументируемым и явным для других разработчиков.

4. Вывод

Введение HexFormat в Java 17 решает многие проблемы, с которыми мы традиционно сталкиваемся при выполнении преобразований между байтами и шестнадцатеричными строками.

В этой статье мы рассмотрели наиболее распространенные варианты использования, но HexFormat также поддерживает более нишевые функции. Например, больше методов преобразования и возможность управлять старшей и нижней половиной полного байта.

Официальная документация по HexFormat доступна в документации по Java 17 .

Как обычно, примеры, которые мы представили в этой статье, на GitHub закончились .