技術メモ

神奈川在住のITエンジニアの備忘録。おもにプログラミングやネットワーク技術について、学んだことを自分の中で整理するためにゆるゆると書いています。ちゃんと検証できていない部分もあるのでご参考程度となりますが、誰かのお役に立てれば幸いです。

バイト列と16進ダンプとの変換

バイト列と16進ダンプ文字列との変換について勉強するために作成したテストコード。
binToHexString()は、バイト配列を16進ダンプ文字列に変換するメソッドで、hexStrToBin()は、その逆を行うメソッドになっている。

public class ChangeBinHex {
    public static void main(String[] args) {
        String str = "z";
        String hexStr = binToHexString(str.getBytes());
        System.out.println(hexStr);  // 7a (0111 1100)

        byte[] bytes = hexStrToBin(hexStr);
        for (byte b : bytes) {
            System.out.print(b + " ");  // 122 (0111 1010) : Ascii Code of "z"
        }
        System.out.println();

        String orgStr = new String(bytes);
        System.out.println(orgStr); // z
    }

    private static String binToHexString(byte[] bytes) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            // I want to change as follows.
            // 11000000 -> 00000000 00000000 00000000 11000000 -> C0
            // If no "0xFF", b is changed to int as follows.
            // 11000000 -> 11111111 11111111 11111111 11000000 -> FF FF FF C0
            String s = Integer.toHexString(0xFF & b);
            if (s.length() == 1) {
                hexString.append('0');
            }
            hexString.append(s);
        }
        return hexString.toString();
    }

    private static byte[] hexStrToBin(String hexStr) {
        byte[] bin = new byte[hexStr.length() / 2];
        try {
            for (int i = 0; i < bin.length; i++) {
                // Change a hex string to a numeric value(binary value).
                // Ex. "3f" -> 63
                bin[i] = (byte) Integer.parseInt(hexStr.substring(i * 2, i * 2 + 2), 16);
            }
        } catch (NumberFormatException e) {
            System.err.println("Failed to change hex string to binary value");
            System.exit(1);
        }
        return bin;
    }
}

なお、上記のソース中のコメントにも書いたが、

String s = Integer.toHexString(0xFF & b);

と、「0xFF &」が付いているのは、b の最上位ビットが立っていた場合、「0xFF &」がないと、b がint型に変換される際に上位のビットが 全て 1 で埋められ、もともとのデータ(bit列)との乖離が生じるためである。

以前は、このバイト列と16進ダンプ文字列との変換のイメージがわかず苦手だった。(今でもあまり得意ではないが・・) 今は、以下のようにイメージしている。

  • バイト列→16進ダンプ文字列: バイト列を4bit毎に該当する16進の文字列(0,1,2, .., e, f)に変換する。
  • 16進ダンプ文字列→バイト列: 例えば、16進ダンプ文字列が 3f だったら、それは2進で 0011 1111 というデータに変換される。これは10進で 63 なので、つまり 3f という文字列が 63という数値に変換される。