1. 序章

Javaでは、通常、バイトと16進文字列の間の変換を処理する独自のメソッドを記述します。 ただし、Java17ではjava.util.HexFormat が導入されています。これは、プリミティブ型、バイト配列、またはchar配列から16進文字列への変換およびその逆の変換を可能にするユーティリティクラスです

このチュートリアルでは、 HexFormat の使用方法を調べ、それが提供する機能を示します。

2. Java17より前の16進文字列の処理

16進数のナンバリングシステムは、16の基数を使用して数値を表します。 これは、16個のシンボルで構成されていることを意味します。通常、0〜9の値の場合は0〜9のシンボル、10〜15の値の場合はAFです。

これは、1と0のバイナリ文字列と比較して推論がはるかに簡単であるため、長いバイナリ値を表すための一般的な選択肢です。

16進文字列とバイト配列の間で変換する必要がある場合、開発者は通常、 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();
}

もう1つの一般的な解決策は、Hexユーティリティクラスを含むApacheCommonsCodecライブラリを使用することです。

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

他のチュートリアルの1つでは、この変換を手動で実行するさまざまな方法について説明しています。

3. HexFormat Java17での使用法

HexFormatはJava17標準ライブラリにあり、バイトと16進文字列間の変換を処理できます。 また、いくつかのフォーマットオプションもサポートしています。

3.1. HexFormatの作成

HexFormat の新しいインスタンスを作成する方法は、区切り文字のサポートが必要かどうかによって異なります HexFormat はスレッドセーフであるため、1つのインスタンスを複数のスレッドで使用できます。

HexFormat.of()は最も一般的なユースケースであり、区切り文字のサポートを気にしない場合に使用します。

HexFormat hexFormat = HexFormat.of();

HexFormat.ofDelimiter(“:”)は、区切り文字のサポートに使用できます。この例では、区切り文字としてコロンを使用しています。

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

3.2. 文字列のフォーマット

HexFormat を使用すると、既存のHexFormatオブジェクトにプレフィックス、サフィックス、および区切り文字のフォーマットオプションを追加できます。これらを使用して、現在のStringのフォーマットを制御できます。解析または生成されます。

3つすべてを一緒に使用する例を次に示します。

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

この場合、単純な of()メソッドを使用してオブジェクトを作成し、 withDelimiter()。を使用して区切り文字を追加します。

3.3. バイトと16進文字列変換

HexFormat インスタンスを作成する方法を確認したので、変換を実行する方法を見ていきましょう。

インスタンスを作成する簡単な方法を使用します。

HexFormat hexFormat = HexFormat.of();

次に、これを使用してStringbyte[]に変換しましょう。

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. プリミティブ型から16進文字列への変換

HexFormat は、プリミティブ型から16進文字列への変換もサポートしています。

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

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

3.5. 大文字と小文字の出力

例が示すように、 HexFormat のデフォルトの動作は、小文字の16進値を生成することです。 HexFormatインスタンスを作成するときにwithUpperCase()を呼び出すことで、この動作を変更できます

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

小文字がデフォルトの動作ですが、 withLowerCase()メソッドも存在します。 これは、コードを自己文書化し、他の開発者に明示的にするのに役立ちます。

4. 結論

Java17でのHexFormatの導入により、バイトと16進文字列の間の変換を実行するときに従来直面していた多くの問題が解決されます。

この記事では最も一般的なユースケースを経験してきましたが、HexFormatはよりニッチな機能もサポートしています。 たとえば、より多くの変換方法と、フルバイトの上半分と下半分を管理する機能があります。

HexFormat の公式ドキュメントは、 Java 17docsで入手できます。

いつものように、この記事で紹介した例は、GitHub上のです。