Estoy buscando una manera de convertir una cadena larga (de un volcado), que represente valores hexadecimales en una matriz de bytes.
No podría haberlo redactado mejor que la persona que publicó la misma pregunta aquí .
Pero para mantenerlo original, lo expresaré a mi manera: supongamos que tengo una cadena "00A0BF"
que me gustaría interpretar como
byte[] {0x00,0xA0,0xBf}
¿Qué tengo que hacer?
Soy un novato en Java y terminé usando BigInteger
y vigilando los ceros hexadecimales principales. Pero creo que es feo y estoy seguro de que me falta algo simple.
BigInteger
aquí .String.getBytes()
no funcionará como crees que podría funcionar. Tuve que aprender esto de la manera difícil.if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
Respuestas:
Aquí hay una solución que creo que es mejor que cualquiera publicada hasta ahora:
Razones por las que es una mejora:
Seguro con ceros a la izquierda (a diferencia de BigInteger) y con valores de bytes negativos (a diferencia de Byte.parseByte)
No convierte la cadena en a
char[]
, ni crea objetos StringBuilder y String para cada byte.No dependencias de la biblioteca que pueden no estar disponibles
Siéntase libre de agregar comprobación de argumentos mediante
assert
o excepciones si no se sabe que el argumento es seguro.fuente
One-liners:
Advertencias :
eckes
)Fabian
eso), pero puede tomar el código fuente si su sistema carecejavax.xml
por alguna razón. Gracias a @Bert Regelink
por extraer la fuente.fuente
java.se
conjunto raíz (predeterminado) , por lo que resultará en unClassNotFoundException
mensaje a menos que especifique--add-modules java.se.ee
javax.xml.bind.DatatypeConverter
ya proporciona un método para codificar / decodificar datos Base64. VerparseBase64Binary()
yprintBase64Binary()
.DataTypeConverter
, Java SE 11 ha eliminado por completo la API JAXB y ahora solo se incluye con Java EE. También puede agregarlo como una dependencia de Maven, como se sugiere aquí: stackoverflow.com/a/43574427/7347751La clase Hex en commons-codec debería hacerlo por usted.
http://commons.apache.org/codec/
fuente
Ahora puede utilizar BaseEncoding en
guava
lograr esto.Para revertirlo use
fuente
En realidad, creo que la solución de BigInteger es muy buena:
Editar: No es seguro para los ceros a la izquierda , como lo señala el afiche.
fuente
Para aquellos de ustedes interesados en el código real detrás de One-liners de FractalizeR (necesitaba eso ya que javax.xml.bind no está disponible para Android (por defecto)), esto viene de com.sun.xml.internal.bind. DatatypeConverterImpl.java :
fuente
El
HexBinaryAdapter
proporciona la capacidad de reunir y desmarcar entreString
ybyte[]
.Ese es solo un ejemplo que escribí ... En realidad solo lo uso como está y no necesito hacer un método separado para usarlo.
fuente
Aquí hay un método que realmente funciona (basado en varias respuestas semicorrectas anteriores):
El único problema posible que puedo ver es si la cadena de entrada es extremadamente larga; llamar a toCharArray () hace una copia de la matriz interna de la cadena.
EDITAR: Ah, y por cierto, los bytes están firmados en Java, por lo que su cadena de entrada se convierte a [0, -96, -65] en lugar de [0, 160, 191]. Pero probablemente ya lo sabías.
fuente
En Android, si está trabajando con hexadecimal, puede probar okio .
uso simple:
y el resultado será
fuente
El
BigInteger()
método de java.math es muy lento y no es recomendable.Integer.parseInt(HEXString, 16)
puede causar problemas con algunos caracteres sin convertir a Digit / Integer
Un buen método de trabajo:
Función:
Diviértete, buena suerte
fuente
EDITAR: como señaló @mmyers, este método no funciona en la entrada que contiene subcadenas correspondientes a bytes con el conjunto de bits alto ("80" - "FF"). La explicación está en ID de error: 6259307 Byte.parseByte no funciona como se anuncia en la documentación del SDK .
fuente
Para lo que vale, aquí hay otra versión que admite cadenas de longitud impar, sin recurrir a la concatenación de cadenas.
fuente
Siempre he usado un método como
Este método se divide en valores hexadecimales delimitados por espacios, pero no sería difícil dividir la cadena en ningún otro criterio, como en grupos de dos caracteres.
fuente
Byte
/byte
: bit más alto establecido sin guía -)Me gusta la solución Character.digit, pero así es como la resolví
fuente
El Código presentado por Bert Regelink simplemente no funciona. Intenta lo siguiente:
fuente
Encontré que Kernel Panic tenía la solución más útil para mí, pero tuve problemas si la cadena hexadecimal era un número impar. lo resolvió de esta manera:
Estoy agregando un número de números hexadecimales a una matriz, por lo que paso la referencia a la matriz que estoy usando, y el int que necesito convertido y devolviendo la posición relativa del siguiente número hexadecimal. Entonces, la matriz de bytes final tiene [0] número de pares hexadecimales, [1] pares hexadecimales, luego el número de pares ...
fuente
Basado en la solución votada, lo siguiente debería ser un poco más eficiente:
Porque: la conversión inicial a una matriz de caracteres ahorra las verificaciones de longitud en charAt
fuente
Si tiene preferencia por las secuencias Java 8 como su estilo de codificación, esto se puede lograr utilizando solo primitivas JDK.
Los
, 0, s2.size()
parámetros en la función de concatenación de colector se pueden omitir si no le importa atraparIOException
.fuente
fuente
Mi solución formal:
Es como la función PHP hex2bin () pero en estilo Java.
Ejemplo:
fuente
Tarde a la fiesta, pero he amalgamado la respuesta anterior de DaveL en una clase con la acción inversa, por si acaso ayuda.
Y clase de prueba JUnit:
fuente
Sé que este es un hilo muy antiguo, pero todavía me gusta agregar el valor de mi centavo.
Si realmente necesito codificar un convertidor de cadena hexadecimal simple a binario, me gustaría hacerlo de la siguiente manera.
fuente
De lejos, no es la solución más limpia. Pero funciona para mí y está bien formateado:
La salida:
fuente
Creo que lo hará por ti. Lo combiné a partir de una función similar que devolvió los datos como una cadena:
fuente
Para mí, esta fue la solución, HEX = "FF01" y luego dividido en FF (255) y 01 (01)
fuente