Hex to String en Java El rendimiento es demasiado lento

Tengo el siguiente método para mi programa android, escrito en Java.

El método toma una cadena de hex y devuelve una cadena del mismo texto escrito en ascii.

public static String hexToString(String hex) { StringBuilder sb = new StringBuilder(); for (int count = 0; count < hex.length() - 1; count += 2) { String output = hex.substring(count, (count + 2)); //grab the hex in pairs int decimal = Integer.parseInt(output, 16); //convert hex to decimal sb.append((char)decimal); //convert the decimal to character } return sb.toString(); } 

El método funciona bien, sin embargo mi programa es muy crítico en el tiempo y este método es potencialmente llamado decenas de miles de veces. Al analizar los bits lentos de mi programa, este método tarda demasiado tiempo debido a:

 Integer.parseInt(output, 16); 

y

 hex.substring(count, (count + 2)); 

En el orden de la primera más lenta.

¿Alguien sabe de un método más rápido de lograr lo mismo?

No cree una nueva String en cada iteración. Una forma de mejorar el rendimiento sería utilizar una matriz de caracteres y aplicar operaciones matemáticas por carácter.

 public static String hexToString(String hex) { StringBuilder sb = new StringBuilder(); char[] hexData = hex.toCharArray(); for (int count = 0; count < hexData.length - 1; count += 2) { int firstDigit = Character.digit(hexData[count], 16); int lastDigit = Character.digit(hexData[count + 1], 16); int decimal = firstDigit * 16 + lastDigit; sb.append((char)decimal); } return sb.toString(); } 

Más información sobre este método:

  • Character#digit

Además, si está analizando la cadena hexadecimal en pares, puede usar una tabla de búsqueda como @ L7ColWinters sugiere:

 private static final Map<String, Character> lookupHex = new HashMap<String, Character>(); static { for(int i = 0; i < 256; i++) { String key = Integer.toHexString(i); Character value = (char)(Integer.parseInt(key, 16)); lookupHex.put(key, value); } } public static String hexToString(String hex) { StringBuilder sb = new StringBuilder(); for (int count = 0; count < hex.length() - 1; count += 2) { String output = hex.substring(count, (count + 2)); sb.append((char)lookupHex.get(output)); } return sb.toString(); } 

¿Qué pasa con este …

 public static String hexToString(final String str) { return new String(new BigInteger(str, 16).toByteArray()); } 

Otra alternativa sería simplemente hacer algunas aritmética simple:

 public static int hexCharToInt(char c) { int result = 0; if(c >= 'A' && c <= 'F') { result += (c - 'A' + 10); } else if( c >= '0' && c <= '9') { result += (c - '0'); } return result; } public static String hexToString(String hex) { StringBuilder sb = new StringBuilder(); for (int count = 0; count < hex.length() - 1; count += 2) { char c1 = hex.charAt(count); char c2 = hex.charAt(count + 1); int decimal = hexCharToInt(c1) * 16 + hexCharToInt(c2); sb.append((char)decimal); //convert the decimal to character } return sb.toString(); } 

Pruébelo y vea qué solución funciona mejor en su sistema.

Este código fue tomado de la clase Hex de Apache Commons Codec y simplificado un poco. (Eliminado algunos controles de rango, etc., lo cual no es necesario para entenderlo aquí.) En la práctica se desea usar la implementación original.

 /** * Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The * returned array will be half the length of the passed array, as it takes two characters to represent any given * byte. An exception is thrown if the passed char array has an odd number of elements. * * @param data * An array of characters containing hexadecimal digits * @return A byte array containing binary data decoded from the supplied char array. * @throws DecoderException * Thrown if an odd number or illegal of characters is supplied */ public static byte[] decodeHex(char[] data) throws DecoderException { int len = data.length; byte[] out = new byte[len >> 1]; // two characters form the hex value. for (int i = 0, j = 0; j < len; i++) { int f = Character.digit(data[j], 16) << 4; j++; f = f | Character.digit(data[j], 16); j++; out[i] = (byte) (f & 0xFF); } return out; } 

Puede utilizar el byte[] devuelto byte[] para construir un objeto String posteriormente.

Así que cuando se utiliza Apache Commons Codec entonces su método se ve así:

 public static String hexToString(String hex) throws UnsupportedEncodingException, DecoderException { return new String(Hex.decodeHex(hex.toCharArray()), "US-ASCII"); } 
  • ¿Cómo implementar correctamente el feed (similar a Facebook / Instagram) en Android?
  • Reserva de almacenamiento interno del dispositivo Android para futuros registros críticos de aplicaciones
  • Cómo maximizar la eficiencia en este complejo escenario de transferencia de datos
  • Variables estáticas, patrón y rendimiento de Android
  • Las imágenes de gridview de Android en caché, en las imágenes de desplazamiento se repiten antes de ser reemplazadas
  • Android - Prevenga la pantalla blanca al inicio
  • Mejor manera de mostrar datos de flujo en la vista de lista de Android
  • ¿Es crucial para el rendimiento tener ViewHolder como estática en un patrón de ViewHolder?
  • Android: dibujar fondo sin GPU OverDraw como WhatsApp
  • ¿Cuáles son las ventajas / desventajas de pasar argumentos al constructor AsyncTask?
  • Obtén velocidad de un evento onTouch ACTION_MOVE en Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.