2014-09-03

Convertir String Hexadecimal en array de bytes en Java

Os presento el método inverso al de Convertir array de bytes en String de los valores en Hexadecimal

El método más optimizado que he encontrado en Java es el siguiente:
byte[] javax.xml.bind.DatatypeConverter.parseHexBinary(String lexicalXSDHexBinary)
Para mostrar su eficiencia voy a compararlo con este otro método [stackoverflow.com] bastante bien valorado por los usuarios:
    private static byte[] hexStringToByteArray(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }
Y para ello, aprovecho para mostrar como se puede hacer un pequeño benchmark comparativo:
import javax.xml.bind.DatatypeConverter;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * @author Raul
 */
public final class Benchmark {

    private static byte[] hexStringToByteArray(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }

    private static final char[] VALORES = "0123456789ABCDEF".toCharArray();
    private static final int MIN = 0;
    private static final int MAX = 15;

    private static final int NUM_TESTS = 1000000;
    private static final int LENGTH_HEX = 64;

    private static final long TIME_ACCURACY = 1000000;

    public static void main(String[] args) {
        // Preparamos los tests
        Random random = new Random();
        int range = MAX - MIN + 1;
        List<String> tests = new LinkedList<String>();
        for (int i = 0; i < NUM_TESTS; i++) {
            StringBuilder sb = new StringBuilder(LENGTH_HEX);
            for (int b = 0; b < LENGTH_HEX; b++) {
                int randomPos = random.nextInt(range) + MIN;
                sb.append(VALORES[randomPos]);
            }
            tests.add(sb.toString());
        }

        // Iniciamos
        long startTime = 0, endTime = 0;
        System.gc();

        // DatatypeConverter
        startTime = System.nanoTime();
        for (String test : tests) {
            byte[] result = DatatypeConverter.parseHexBinary(test);
        }
        endTime = System.nanoTime();
        System.out.printf("%22s %10d%n", "DatatypeConverter:",
                (endTime - startTime) / TIME_ACCURACY);
        System.gc();

        // hexStringToByteArray
        startTime = System.nanoTime();
        for (String test : tests) {
            byte[] result = hexStringToByteArray(test);
        }
        endTime = System.nanoTime();
        System.out.printf("%22s %10d%n", "hexStringToByteArray:",
                (endTime - startTime) / TIME_ACCURACY);
        System.gc();
    }

}
Resultado:
    DatatypeConverter:        663
 hexStringToByteArray:        908

El paquete de DatatypeConverter no está disponible en Android, así que los que necesitéis este método podéis utilizar el hexStringToByteArray expuesto aquí, o el código del parseHexBinary extraído del propio paquete y que podéis encontrar en http://stackoverflow.com/a/11139098

No hay comentarios:

Publicar un comentario