こんにちは、エキサイト株式会社の平石です。エキサイトホールディングス Advent Calendar 2023の19日目を担当いたします。
今回は、Javaで整数型やbyte配列と16進表記の文字列との間の変換を行なう方法をご紹介します。
整数 → 16進表記 の変換
まずは、通常の10進表記(として表示される)整数を16進表記に変換してみます。
標準ライブラリのみを使う場合には、主に2つの方法があります。
IntegerやLongクラスのstaticメソッド
IntegerやLongクラスには、intやlongを16進表記に変換するstaticメソッドが用意されています。
var hexFromInt = Integer.toHexString(30); var hexFromLong = Long.toHexString(255L); System.out.println("30の16進表記: " + hexFromInt); System.out.println("255Lの16進表記: " + hexFromLong);
30の16進表記: 1e 255Lの16進表記: ff
HexFormatクラスを使う
Java 17からはHexFormat
クラスというものを利用することができます。
byte byteNum = 100; short shortNum = 10000; int intNum = 1000000; long longNum = 100000000; String hexFromByte = HexFormat.of().toHexDigits(byteNum); String hexFromShort = HexFormat.of().toHexDigits(shortNum); String hexFromInt = HexFormat.of().toHexDigits(intNum); String hexFromLong = HexFormat.of().toHexDigits(longNum); System.out.println("byteNumの16進表記: " + hexFromByte); System.out.println("shortNumの16進表記: " + hexFromShort); System.out.println("intNumの16進表記: " + hexFromInt); System.out.println("longNumの16進表記: " + hexFromLong);
byteNumの16進表記: 64 shortNumの16進表記: 2710 intNumの16進表記: 000f4240 longNumの16進表記: 0000000005f5e100
このように、toHexDigits
に渡す引数の型によって最終的に出力される16進表記の長さも変わります。
Long
型の整数は8バイトなので、1L
のような値を渡しても1
ではなく0000000000000001
が返ります。
一方、Integer
やLong
のstaticメソッドを利用するときには、1
が返ります。
これが、この2つの方法の大きな違いですので、状況によって使い分けると良いでしょう。
HexFormat
クラスについては後に詳しく紹介します。
16進表記 → 整数の変換
こちらも標準ライブラリのみを利用するのであれば、主に以下の2つの方法があります。
IntegerやLongクラスのstaticメソッド
IntegerやLongクラスのstaticメソッドを利用するには以下のようにします。
byte byteFromHex = Byte.parseByte("f", 16); short shortFromHex = Short.parseShort("fff", 16); int intFromHex = Integer.parseInt("fffff", 16); long longFromHex = Long.parseLong("fffffff", 16); System.out.println("f のパース結果: " + byteFromHex); System.out.println("fff のパース結果: " + shortFromHex); System.out.println("fffff のパース結果: " + intFromHex); System.out.println("fffffff のパース結果: " + longFromHex);
f のパース結果: 15 fff のパース結果: 4095 fffff のパース結果: 1048575 fffffff のパース結果: 268435455
HexFormatクラスを使う
Java 17以降は、HexFormat
クラスのstaticメソッドを利用しても、16進表記の文字列を整数に変換することができます。
int intFromHex = HexFormat.fromHexDigits("fffff"); long longFromHex = HexFormat.fromHexDigitsToLong("fffffff");
fffff のパース結果: 1048575 fffffff のパース結果: 268435455
HexFormatクラスによるbyte配列と16進表記の変換
HexFormat
クラスを利用すれば、byte配列と16進表記の変換を行うことができます。
byte配列 → 16進表記
byte配列から16進表記の文字列に変換するには、formatHex
メソッドを利用します。
byte[] bytes = {1, 15, 120, 127}; String byteHex = HexFormat.of().formatHex(bytes); System.out.println(byteHex);
010f787f
ちなみに、負の数ではff
(-1)から順に80
(-128)となります。
(2の補数表現で-1は11111111
なので当然といえば当然ですね。)
byte[] bytes = {-1, -2, -127, -128}; String byteHex = HexFormat.of().formatHex(bytes);
fffe8180
このメソッドを使って、ランダムな16進表記の文字列を作成できます。
final SecureRandom secureRandom = new SecureRandom(); final int numString = 64; // 生成したいランダムな文字列の文字数 final byte[] randomByte = new byte[numString / 2]; secureRandom.nextBytes(randomByte); final String randomHex = HexFormat.of().formatHex(randomByte); System.out.println(randomHex);
byte 1つにつき2文字に変換されるので、byte配列の長さはnumString / 2
としています。
16進表記 → byte配列
逆に16進表記の文字列からbyte配列に変換するには、parseHex
メソッドを利用します。
先ほどの例の変換後の文字列を、byte配列に戻してみましょう。
byte[] bytesFromHex = HexFormat.of().parseHex(byteHex); // byteHex = 010f787f System.out.println(Arrays.toString(bytesFromHex));
[1, 15, 120, 127]
HexFormatクラスの詳細
最後に、HexFormat
クラスの詳細についてみてみます。
これまでの例ではHexFormat.of()
と書いてHexFormat
のインスタンスを取得していましたが、HexFormat
のインスタンスの取得のためにはofDelimiter()
というstaticメソッドもあります。
of()
はdelimiter
なしのフォーマッター、ofDelimiter()
はdelimitter
ありのフォーマッターを返します。
delimiter
は、基本的には byte配列を16進表記に変換する際に区切り文字として使われます。
(toHexDigits
を使って単一のbyteや、int、longを変換する際には、delimiterは使われません。)
例えば、以下のように使います。
byte[] bytes = {1, 15, 120, 127}; String byteHex = HexFormat.ofDelimiter(":").formatHex(bytes); System.out.println(byteHex); byte[] bytesFromHex = HexFormat.ofDelimiter(":").parseHex(byteHex); System.out.println(Arrays.toString(bytesFromHex));
01:0f:78:7f [1, 15, 120, 127]
その他、HexFormatクラスのインスタンスに対しては、フォーマットの際の詳細設定を行うことができます。
prefix, suffix, delimiterはformatHex
とparseHex
のみで利用されます。
- withDelimiter・・・・delimiterを改めて指定できる
- withLowerCase・・・16進表記に小文字(a ~ f)を使用するようになる
- withUpperCase・・・16進表記に大文字(A ~ F)を使用するようになる
- withPrefix・・・・・prefixを指定
- withSuffix・・・・・suffixを指定
HexFormat hexFormat = HexFormat.of() .withDelimiter(", ") .withPrefix("#") .withSuffix(";") .withUpperCase(); byte[] bytes = {1, 15, 120, 127}; String hex = hexFormat.formatHex(bytes); System.out.println(hex); System.out.println(hexFormat.toHexDigits(255));
#01;, #0F;, #78;, #7F; // prefix, suffix, delimiterが適用される 000000FF // 単一の値の変換ではprefix, suffix, delimiterは適用されない
終わりに
今回は、Javaで整数型やbyte配列と16進表記の文字列との間の変換方法をご紹介しました。
では、また次回。