com.peterphi.std.util.HexHelper Maven / Gradle / Ivy
The newest version!
package com.peterphi.std.util;
import java.util.Random;
import java.util.StringTokenizer;
/**
* A helper class which handles encoding and decoding hexidecimal
*/
public class HexHelper
{
private HexHelper()
{
}
private static final char[] hex = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
/**
* Decodes a hexidecimal string into a series of bytes
*
* @param value
*
* @return
*/
public static final byte[] fromHex(final String value)
{
if (value.length() == 0)
return new byte[0];
else if (value.indexOf(':') != -1)
return fromHex(':', value);
else if (value.length() % 2 != 0)
throw new IllegalArgumentException("Invalid hex specified: uneven number of digits passed for byte[] conversion");
final byte[] buffer = new byte[value.length() / 2];
// i tracks input position, j tracks output position
int j = 0;
for (int i = 0; i < buffer.length; i++)
{
buffer[i] = (byte) Integer.parseInt(value.substring(j, j + 2), 16);
j += 2;
}
return buffer;
}
/**
* Decodes a hexidecimal string (optionally with separator
characters separating each two-digit pair)
* Multiple runs of the separator will be ignored (eg. AA::BB will result in [0xAA,0xBB]
, not
* [0xAA,0x00,0xBB]
)
*
* @param separator
* the separator character
* @param value
*
* @return
*/
public static final byte[] fromHex(final char separator, final String value)
{
if (value.length() == 0)
return new byte[0];
final String sepString = new String(new char[]{separator});
final StringTokenizer t = new StringTokenizer(value, sepString, false);
final byte[] buffer = new byte[t.countTokens()];
int i = 0;
while (t.hasMoreTokens())
{
final String hex = t.nextToken();
if (hex.length() == 2)
buffer[i++] = (byte) Integer.parseInt(hex, 16);
else
throw new IllegalArgumentException("Hex section of length " +
hex.length() +
" encountered inside hex string: " +
value +
" with separator " +
separator);
}
return buffer;
}
/**
* Generates a number of random bytes which can then be manipulated and/or converted to hex
* Uses a new instance of java.util.Random
*
* @param bytes
*
* @return
*/
public static final byte[] generateBytes(final int bytes)
{
return generateBytes(new Random(), bytes);
}
/**
* Generates a number of random bytes which can then be manipulated and/or converted to hex
*
* @param RANDOM
* the random number generator to use
* @param bytes
*
* @return
*/
public static final byte[] generateBytes(final Random rand, final int bytes)
{
if (bytes < 1)
throw new IllegalArgumentException("bytes must be >= 1");
final byte[] buffer = new byte[bytes];
rand.nextBytes(buffer);
return buffer;
}
/**
* Generates a hexidecimal String of length characters
*
* @param characters
* the number of characters in the resulting String
*
* @return
*/
public static final String generateHex(final int characters)
{
return generateHex(new Random(), characters);
}
/**
* Generates a hexidecimal String of length characters
*
* @param random
* the random number generator to use
* @param characters
* the number of characters in the resulting String
*
* @return
*/
public static final String generateHex(final Random random, final int characters)
{
if (characters < 1)
throw new IllegalArgumentException("characters must be >= 1");
final char[] str = new char[characters];
for (int i = 0; i < characters; i++)
{
str[i] = hex[random.nextInt(16)];
}
return new String(str);
}
/**
* Encodes a series of bytes into a hexidecimal string (potentially with leading zeroes) with no separators between each
* source byte
*
* @param bin
*
* @return
*/
public static final String toHex(final byte... bin)
{
if (bin == null || bin.length == 0)
return "";
final char[] buffer = new char[bin.length * 2];
// i tracks input position, j tracks output position
for (int i = 0, j = 0; i < bin.length; i++)
{
final byte b = bin[i];
buffer[j++] = hex[(b >> 4) & 0x0F];
buffer[j++] = hex[b & 0x0F];
}
return new String(buffer);
}
/**
* Encodes a series of bytes into a hexidecimal string with each source byte (represented in the output as a 2 digit
* hexidecimal pair) separated by separator
*
* @param separator
* The character to insert between each byte (for example, ':'
)
* @param bin
* the series of bytes to encode
*
* @return a hexidecimal string with each source byte (represented in the output as a 2 digit hexidecimal pair) separated by
* separator
*/
public static final String toHex(final char separator, final byte... bin)
{
if (bin == null || bin.length == 0)
return "";
char[] buffer = new char[(bin.length * 3) - 1];
int end = bin.length - 1;
int base = 0; // Store the index of buffer we're inserting into
for (int i = 0; i < bin.length; i++)
{
byte b = bin[i];
buffer[base++] = hex[(b >> 4) & 0x0F];
buffer[base++] = hex[b & 0x0F];
if (i != end)
buffer[base++] = separator;
}
return new String(buffer);
}
}