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.
- Enviar eficientemente int a través de sockets en Java
- ¿Gradle escala de rendimiento bien con el número de núcleos de la CPU
- Problema de velocidad de Android con la deserialización mediante SimpleXML
- Mi aplicación se redujo significativamente en Android 4.0
- ¿Cómo configurar el desplazamiento perfomance para webview?
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?
- Es mejor inflar o instanciar los controles en Android?
- Mover instancias de Set a otro en Scala
- Haga que la animación de Android sea más suave cuando se muestre el teclado durante la animación
- ¿Estoy bebiendo la plataforma / hardware?
- ¿Cuál es la diferencia entre BaseAdapter y ArrayAdapter?
- Edittext Mensaje de error de validación en android?
- Android - ¿Cómo investigo una ANR?
- Consejos sobre dibujo de alto rendimiento en Android
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"); }
- Canvas.toDataURL no da como resultado datos de imagen / jpeg
- Menú de desbordamiento de la barra de acciones abrir / cerrar escucha