Hexadecimal Encoding/Decoding with Java


Representing numbers in hexadecimal form, at least in programming, might still be a very difficult problem. There are plenty of googled results for how we do it in any languages.

DatatypeConverter from JAXB

First and foremost way is definitely using one of existing classes and methods in JDK.

Here comes OpenJDK’s implemention of those method.

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if (len % 2 != 0) {
        throw new IllegalArgumentException("hexBinary needs to be even-length: " + s);
    }

    byte[] out = new byte[len / 2];

    for (int i = 0; i < len; i += 2) {
        int h = hexToBin(s.charAt(i));
        int l = hexToBin(s.charAt(i + 1));
        if (h == -1 || l == -1) {
            throw new IllegalArgumentException("contains illegal character for hexBinary: " + s);
        }

        out[i / 2] = (byte) (h * 16 + l);
    }

    return out;
}

private static int hexToBin(char ch) {
    if ('0' <= ch && ch <= '9') {
        return ch - '0';
    }
    if ('A' <= ch && ch <= 'F') {
        return ch - 'A' + 10;
    }
    if ('a' <= ch && ch <= 'f') {
        return ch - 'a' + 10;
    }
    return -1;
}

private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length * 2);
    for (byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}

half

number (4bit) character (8bit)
0x0 ( 0) 0x30 ('0')
0x1 ( 1) 0x31 ('1')
0x2 ( 2) 0x32 ('2')
0x3 ( 3) 0x33 ('3')
0x4 ( 4) 0x34 ('4')
0x5 ( 5) 0x35 ('5')
0x6 ( 6) 0x36 ('6')
0x7 ( 7) 0x37 ('7')
0x8 ( 8) 0x38 ('8')
0x9 ( 9) 0x39 ('9')
0xA (10) 0x41 ('A')
0xB (11) 0x42 ('B')
0xC (12) 0x43 ('C')
0xA (13) 0x44 ('D')
0xE (14) 0x45 ('E')
0xF (15) 0x46 ('F')
protected static int encodeHalf(final int decoded) {

    if (decoded < 0x0A) {
        return decoded + 0x30;
    } else {
        return decoded + 0x37;
    }
}


protected static int decodeHalf(final int encoded) {

    if (encoded < 0x41) {
        return encoded - 0x30;
    } else {
        return encoded - 0x37;
    }
}

single

number (8bit) character (16bit)
0x00 (  0) 0x30 0x30 ('00')
.... (  .) .... .... ('..')
0x09 (  9) 0x30 0x39 ('09')
0x0A ( 10) 0x30 0x41 ('0A')
.... ( ..) .... .... ('..')
0x0F ( 15) 0x30 0x46 ('0F')
0x10 ( 16) 0x31 0x30 ('10')
.... ( ..) .... .... ('..')
0x63 ( 99) 0x36 0x33 ('63')
0x64 (100) 0x36 0x34 ('64')
0xC7 (199) 0x43 0x37 ('C7')
0xC8 (200) 0x43 0x38 ('C8')
0xC9 (201) 0x43 0x39 ('C9')
.... (...) .... .... ('..')
0xFF (255) 0x46 0x46 ('FF')
protected static byte[] encodeSingle(final int decoded) {

    final byte[] encoded = new byte[2];

    encoded[0] = (byte) encodeHalf(decoded >> 4);
    encoded[1] = (byte) encodeHalf(decoded & 0x0F);

    return encoded;
}


protected static int decodeSingle(final byte[] encoded) {

    final int high = decodeHalf(encoded[0] & 0xFF);
    final int low = decodeHalf(encoded[1] & 0xFF);

    return (high << 4 | low);
}

multiple

protected static void encodeSingle(final int decoded, final byte[] encoded, final int offset);

protected static int decodeSingle(final byte[] encoded, final int offset);

protected static byte[] encodeMultiple(final byte[] decoded);

protected static byte[] decodeMultiple(final byte[] encoded);

sources

$ svn co http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/ hex-codec
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s