Tengo una matriz de bytes. Quiero que cada cadena de bytes de esa matriz se convierta a sus valores hexadecimales correspondientes.
¿Hay alguna función en Java para convertir una matriz de bytes a hexadecimal?
Tengo una matriz de bytes. Quiero que cada cadena de bytes de esa matriz se convierta a sus valores hexadecimales correspondientes.
¿Hay alguna función en Java para convertir una matriz de bytes a hexadecimal?
Respuestas:
byte[] bytes = {-1, 0, 1, 2, 3 };
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
System.out.println(sb.toString());
// prints "FF 00 01 02 03 "
java.util.Formatter
sintaxis
%[flags][width]conversion
'0'
: el resultado se rellenará con ceros2
'X'
: el resultado se formatea como un entero hexadecimal, mayúsculaMirando el texto de la pregunta, también es posible que esto sea lo que se solicita:
String[] arr = {"-1", "0", "10", "20" };
for (int i = 0; i < arr.length; i++) {
arr[i] = String.format("%02x", Byte.parseByte(arr[i]));
}
System.out.println(java.util.Arrays.toString(arr));
// prints "[ff, 00, 0a, 14]"
Varias respuestas aquí utiliza Integer.toHexString(int)
; Esto es factible, pero con algunas advertencias. Como el parámetro es an int
, se realiza una conversión primitiva de ampliación al byte
argumento, que implica la extensión del signo.
byte b = -1;
System.out.println(Integer.toHexString(b));
// prints "ffffffff"
El 8 bits byte
, que está firmado en Java, está extendido a 32 bits int
. Para deshacer efectivamente esta extensión de signo, se puede enmascarar byte
con 0xFF
.
byte b = -1;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "ff"
Otro problema con el uso toHexString
es que no rellena con ceros:
byte b = 10;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "a"
Ambos factores combinados deberían hacer que la String.format
solución sea más preferible.
byte
, desde -128
hasta 127
, inclusivetoHexString
. Tienes que enmascararlo & 0xFF
, Integer.toHexString(-46 & 0xFF)
es decir, es "d2"
.
byte
valor & 0xFF
cada vez. la format
solución anterior también puede requerir enmascarar dependiendo de lo que realmente esté usando como argumento.
Estoy publicando porque ninguna de las respuestas existentes explica por qué funcionan sus enfoques, lo que creo que es realmente importante para este problema. En algunos casos, esto hace que la solución propuesta parezca innecesariamente complicada y sutil. Para ilustrar, proporcionaré un enfoque bastante sencillo, pero proporcionaré un poco más de detalle para ayudar a ilustrar por qué funciona.
En primer lugar, ¿qué estamos tratando de hacer? Queremos convertir un valor de byte (o una matriz de bytes) en una cadena que represente un valor hexadecimal en ASCII. Entonces, el primer paso es descubrir exactamente qué es un byte en Java:
El tipo de datos de byte es un entero de dos bits con signo de 8 bits . Tiene un valor mínimo de -128 y un valor máximo de 127 (inclusive). El tipo de datos de byte puede ser útil para ahorrar memoria en matrices grandes, donde el ahorro de memoria realmente importa. También se pueden usar en lugar de int, donde sus límites ayudan a aclarar su código; El hecho de que el rango de una variable sea limitado puede servir como una forma de documentación.
¿Qué significa esto? Algunas cosas: Primero y más importante, significa que estamos trabajando con 8 bits . Entonces, por ejemplo, podemos escribir el número 2 como 0000 0010. Sin embargo, dado que es el complemento de dos, escribimos un 2 negativo como este: 1111 1110. Lo que también significa es que convertir a hexadecimal es muy sencillo. Es decir, simplemente convierte cada segmento de 4 bits directamente en hexadecimal. Tenga en cuenta que para dar sentido a los números negativos en este esquema, primero deberá comprender el complemento de dos. Si aún no comprende el complemento a dos, puede leer una excelente explicación aquí: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Una vez que un número está en el complemento de dos, es muy simple convertirlo a hexadecimal. En general, la conversión de binario a hexadecimal es muy sencilla y, como verá en los siguientes dos ejemplos, puede pasar directamente del complemento de dos a hexadecimal.
Ejemplo 1: Convierte 2 a Hex.
1) Primero convierta 2 a binario en el complemento a dos:
2 (base 10) = 0000 0010 (base 2)
2) Ahora convierta binario a hexadecimal:
0000 = 0x0 in hex
0010 = 0x2 in hex
therefore 2 = 0000 0010 = 0x02.
Ejemplo 2: Convertir -2 (en complemento de dos) a Hex.
1) Primero convierta -2 a binario en el complemento a dos:
-2 (base 10) = 0000 0010 (direct conversion to binary)
1111 1101 (invert bits)
1111 1110 (add 1)
therefore: -2 = 1111 1110 (in two's complement)
2) Ahora Convierte a Hex:
1111 = 0xF in hex
1110 = 0xE in hex
therefore: -2 = 1111 1110 = 0xFE.
Ahora que hemos cubierto el concepto, descubrirá que podemos lograr lo que queremos con un simple enmascaramiento y cambio. La clave para entender es que el byte que está intentando convertir ya está en el complemento de dos. No haces esta conversión tú mismo. Creo que este es un importante punto de confusión sobre este tema. Tomemos, por ejemplo, la siguiente matriz de bytes:
byte[] bytes = new byte[]{-2,2};
Los convertimos manualmente a hexadecimal, arriba, pero ¿cómo podemos hacerlo en Java? Así es cómo:
Paso 1: Crea un StringBuffer para mantener nuestro cálculo.
StringBuffer buffer = new StringBuffer();
Paso 2: aísle los bits de orden superior, conviértalos a hexadecimal y agréguelos al búfer
Dado el número binario 1111 1110, podemos aislar los bits de orden superior desplazándolos primero por 4 y luego poniendo a cero el resto del número. Lógicamente, esto es simple, sin embargo, los detalles de implementación en Java (y en muchos idiomas) introducen una arruga debido a la extensión del signo. Esencialmente, cuando cambia un valor de byte, Java primero convierte su valor a un número entero y luego realiza la extensión de signo. Entonces, si bien esperaría que 1111 1110 >> 4 sea 0000 1111, en realidad, en Java se representa como el complemento de dos 0xFFFFFFFF.
Volviendo a nuestro ejemplo:
1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)
Entonces podemos aislar los bits con una máscara:
1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex.
En Java podemos hacer todo esto de una vez:
Character.forDigit((bytes[0] >> 4) & 0xF, 16);
La función forDigit solo asigna el número que le pasa al conjunto de números hexadecimales 0-F.
Paso 3: A continuación, necesitamos aislar los bits de orden inferior. Como los bits que queremos ya están en la posición correcta, podemos enmascararlos:
1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.
Como antes, en Java podemos hacer todo esto de una vez:
Character.forDigit((bytes[0] & 0xF), 16);
Al unir todo esto, podemos hacerlo como un bucle for y convertir toda la matriz:
for(int i=0; i < bytes.length; i++){
buffer.append(Character.forDigit((bytes[i] >> 4) & 0xF, 16));
buffer.append(Character.forDigit((bytes[i] & 0xF), 16));
}
Esperemos que esta explicación aclare las cosas para aquellos de ustedes que se preguntan exactamente qué está sucediendo en los muchos ejemplos que encontrarán en Internet. ¡Espero no haber cometido ningún error atroz, pero las sugerencias y correcciones son bienvenidas!
Character.digit()
, como(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
La forma más rápida que he encontrado para hacer esto es la siguiente:
private static final String HEXES = "0123456789ABCDEF";
static String getHex(byte[] raw) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
Es ~ 50 veces más rápido que String.format
. si quieres probarlo:
public class MyTest{
private static final String HEXES = "0123456789ABCDEF";
@Test
public void test_get_hex() {
byte[] raw = {
(byte) 0xd0, (byte) 0x0b, (byte) 0x01, (byte) 0x2a, (byte) 0x63,
(byte) 0x78, (byte) 0x01, (byte) 0x2e, (byte) 0xe3, (byte) 0x6c,
(byte) 0xd2, (byte) 0xb0, (byte) 0x78, (byte) 0x51, (byte) 0x73,
(byte) 0x34, (byte) 0xaf, (byte) 0xbb, (byte) 0xa0, (byte) 0x9f,
(byte) 0xc3, (byte) 0xa9, (byte) 0x00, (byte) 0x1e, (byte) 0xd5,
(byte) 0x4b, (byte) 0x89, (byte) 0xa3, (byte) 0x45, (byte) 0x35,
(byte) 0xd6, (byte) 0x10,
};
int N = 77777;
long t;
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
final StringBuilder hex = new StringBuilder(2 * raw.length);
for (final byte b : raw) {
hex.append(HEXES.charAt((b & 0xF0) >> 4)).append(HEXES.charAt((b & 0x0F)));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 50
}
{
t = System.currentTimeMillis();
for (int i = 0; i < N; i++) {
StringBuilder hex = new StringBuilder(2 * raw.length);
for (byte b : raw) {
hex.append(String.format("%02X", b));
}
hex.toString();
}
System.out.println(System.currentTimeMillis() - t); // 2535
}
}
}
Editar : Acabo de encontrar algo un poco más rápido y que se mantiene en una línea, pero no es compatible con JRE 9. Úselo bajo su propio riesgo
import javax.xml.bind.DatatypeConverter;
DatatypeConverter.printHexBinary(raw);
printHexBinary
del código fuente de src.zip de jdk, que parece 1 veces más rápido que el primer método.
Intenta de esta manera:
byte bv = 10;
String hexString = Integer.toHexString(bv);
Tratando con la matriz (si te entendí correctamente):
byte[] bytes = {9, 10, 11, 15, 16};
StringBuffer result = new StringBuffer();
for (byte b : bytes) {
result.append(String.format("%02X ", b));
result.append(" "); // delimiter
}
return result.toString();
Como se mencionó a los poligenelubricantes, String.format()
es la respuesta correcta en comparación con Integer.toHexString()
(ya que trata con los números negativos de la manera correcta).
-1
.
bv
que devuelva un solo carácter hexadecimal . Mientras que el resto del código devuelve una cadena de caracteres hexadecimales . He cambiado el código con el delímetro para que pueda entenderlo ahora.
Integer.toHexString
si enmascarar el byte
con 0xFF
de extensión de signo de deshacer.
La mejor solución es este rudo one-liner:
String hex=DatatypeConverter.printHexBinary(byte[] b);
como se menciona aquí
new BigInteger(byteArray).toString(16)
es el camino a seguir entonces. ¿Son problemas de rendimiento con eso?
Si desea una representación hexadecimal de ancho constante, es decir, en 0A
lugar de A
, para que pueda recuperar los bytes sin ambigüedades, intente format()
:
StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
result.append(String.format("%02X", bb));
}
return result.toString();
Una forma corta y simple de convertir byte[]
a una cadena hexadecimal usando BigInteger
:
import java.math.BigInteger;
byte[] bytes = new byte[] {(byte)255, 10, 20, 30};
String hex = new BigInteger(1, bytes).toString(16);
System.out.println(hex); // ff0a141e
La clase de java.math.BigInteger
clase del sistema integrada ( java.math.BigInteger ) es compatible con datos binarios y hexadecimales:
BigInteger(signum=1, byte[])
para crear un número entero grande byte[]
(establezca su primer parámetro signum
= 1
para manejar correctamente los bytes negativos)BigInteger.toString(16)
para convertir el entero grande en una cadena hexadecimalnew BigInteger("ffa74b", 16)
- no maneja correctamente el cero inicialSi desea tener el cero inicial en el resultado hexadecimal, verifique su tamaño y agregue el cero faltante si es necesario:
if (hex.length() % 2 == 1)
hex = "0" + hex;
Use new BigInteger(1, bytes)
, en lugar de new BigInteger(bytes)
, porque Java está " roto por diseño " y el byte
tipo de datos no contiene bytes, sino enteros pequeños con signo [-128 ... 127]. Si el primer byte es negativo, se BigInteger
supone que pasa un entero grande negativo. Simplemente pase 1
como primer parámetro ( signum=1
).
La conversión de nuevo de hexadecimal abyte[]
es complicada: a veces un cero inicial ingresa en la salida producida y debe limpiarse así:
byte[] bytes = new BigInteger("ffa74b", 16).toByteArray();
if (bytes[0] == 0) {
byte[] newBytes = new byte[bytes.length - 1];
System.arraycopy(bytes, 1, newBytes, 0, newBytes.length);
bytes = newBytes;
}
La última nota es si byte[]
tiene varios ceros a la izquierda, se perderán.
Si está contento de usar una biblioteca externa, la org.apache.commons.codec.binary.Hex
clase tiene un encodeHex
método que toma byte[]
ay devuelve a char[]
. Este método es MUCHO más rápido que la opción de formato y encapsula los detalles de la conversión. También viene con un decodeHex
método para la conversión opuesta.
javax
espacio de nombres no siempre está disponible.
Puede usar el método de la biblioteca de Bouncy Castle Provider :
org.bouncycastle.util.encoders.Hex.toHexString(byteArray);
El paquete Crypto de Bouncy Castle es una implementación Java de algoritmos criptográficos. Este jar contiene el proveedor de JCE y la API ligera para las API de criptografía de Bouncy Castle para JDK 1.5 a JDK 1.8.
Dependencia de Maven:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
o del códec de Apache Commons :
org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);
El paquete Apache Commons Codec contiene codificadores y decodificadores simples para varios formatos, como Base64 y Hexadecimal. Además de estos codificadores y decodificadores ampliamente utilizados, el paquete de códec también mantiene una colección de utilidades de codificación fonética.
Dependencia de Maven:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
Este es el código que he encontrado para ejecutar el más rápido hasta ahora. Lo ejecuté en matrices de bytes 109015 de longitud 32, en 23 ms. Lo estaba ejecutando en una máquina virtual, por lo que probablemente se ejecutará más rápido en metal desnudo.
public static final char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public static char[] encodeHex( final byte[] data ){
final int l = data.length;
final char[] out = new char[l<<1];
for( int i=0,j=0; i<l; i++ ){
out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4];
out[j++] = HEX_DIGITS[0x0F & data[i]];
}
return out;
}
Entonces solo puedes hacer
String s = new String( encodeHex(myByteArray) );
BigInteger n = new BigInteger(byteArray);
String hexa = n.toString(16));
BigInteger(byteArrayOf(-1, 2, 3, 4, 5)).toString(16)
regresa"-fdfcfbfb"
(int) 255
) ya que los bytes de Java están firmados, por lo que el resultado debería ser FF02030405
. Si prueba la solución @Jerinaw anterior, verá que imprimirá la salida correcta. Ver también la solución de Svetlin Nakov a continuación.
Aquí hay una función simple para convertir byte a hexadecimal
private static String convertToHex(byte[] data) {
StringBuffer buf = new StringBuffer();
for (int i = 0; i < data.length; i++) {
int halfbyte = (data[i] >>> 4) & 0x0F;
int two_halfs = 0;
do {
if ((0 <= halfbyte) && (halfbyte <= 9))
buf.append((char) ('0' + halfbyte));
else
buf.append((char) ('a' + (halfbyte - 10)));
halfbyte = data[i] & 0x0F;
} while(two_halfs++ < 1);
}
return buf.toString();
}
Otros han cubierto el caso general. Pero si tiene una matriz de bytes de una forma conocida, por ejemplo, una dirección MAC, entonces puede:
byte[] mac = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };
String str = String.format("%02X:%02X:%02X:%02X:%02X:%02X",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
Crear (y destruir) un montón de String
instancias no es una buena manera si el rendimiento es un problema.
Ignore esos argumentos verbales (duplicados) que verifican las declaraciones if
. Eso es para (otro) propósito educativo.
Proyecto completo de maven: http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/
Codificación ...
/**
* Encodes a single nibble.
*
* @param decoded the nibble to encode.
*
* @return the encoded half octet.
*/
protected static int encodeHalf(final int decoded) {
switch (decoded) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
case 0x08:
case 0x09:
return decoded + 0x30; // 0x30('0') - 0x39('9')
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
return decoded + 0x57; // 0x41('a') - 0x46('f')
default:
throw new IllegalArgumentException("illegal half: " + decoded);
}
}
/**
* Encodes a single octet into two nibbles.
*
* @param decoded the octet to encode.
* @param encoded the array to which each encoded nibbles are written.
* @param offset the offset in the array.
*/
protected static void encodeSingle(final int decoded, final byte[] encoded,
final int offset) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if (encoded.length < 2) {
// not required
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") < 2");
}
if (offset < 0) {
throw new IllegalArgumentException("offset(" + offset + ") < 0");
}
if (offset >= encoded.length - 1) {
throw new IllegalArgumentException(
"offset(" + offset + ") >= encoded.length(" + encoded.length
+ ") - 1");
}
encoded[offset] = (byte) encodeHalf((decoded >> 4) & 0x0F);
encoded[offset + 1] = (byte) encodeHalf(decoded & 0x0F);
}
/**
* Decodes given sequence of octets into a sequence of nibbles.
*
* @param decoded the octets to encode
*
* @return the encoded nibbles.
*/
protected static byte[] encodeMultiple(final byte[] decoded) {
if (decoded == null) {
throw new IllegalArgumentException("null decoded");
}
final byte[] encoded = new byte[decoded.length << 1];
int offset = 0;
for (int i = 0; i < decoded.length; i++) {
encodeSingle(decoded[i], encoded, offset);
offset += 2;
}
return encoded;
}
/**
* Encodes given sequence of octets into a sequence of nibbles.
*
* @param decoded the octets to encode.
*
* @return the encoded nibbles.
*/
public byte[] encode(final byte[] decoded) {
return encodeMultiple(decoded);
}
Descodificación...
/**
* Decodes a single nibble.
*
* @param encoded the nibble to decode.
*
* @return the decoded half octet.
*/
protected static int decodeHalf(final int encoded) {
switch (encoded) {
case 0x30: // '0'
case 0x31: // '1'
case 0x32: // '2'
case 0x33: // '3'
case 0x34: // '4'
case 0x35: // '5'
case 0x36: // '6'
case 0x37: // '7'
case 0x38: // '8'
case 0x39: // '9'
return encoded - 0x30;
case 0x41: // 'A'
case 0x42: // 'B'
case 0x43: // 'C'
case 0x44: // 'D'
case 0x45: // 'E'
case 0x46: // 'F'
return encoded - 0x37;
case 0x61: // 'a'
case 0x62: // 'b'
case 0x63: // 'c'
case 0x64: // 'd'
case 0x65: // 'e'
case 0x66: // 'f'
return encoded - 0x57;
default:
throw new IllegalArgumentException("illegal half: " + encoded);
}
}
/**
* Decodes two nibbles into a single octet.
*
* @param encoded the nibble array.
* @param offset the offset in the array.
*
* @return decoded octet.
*/
protected static int decodeSingle(final byte[] encoded, final int offset) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if (encoded.length < 2) {
// not required
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") < 2");
}
if (offset < 0) {
throw new IllegalArgumentException("offset(" + offset + ") < 0");
}
if (offset >= encoded.length - 1) {
throw new IllegalArgumentException(
"offset(" + offset + ") >= encoded.length(" + encoded.length
+ ") - 1");
}
return (decodeHalf(encoded[offset]) << 4)
| decodeHalf(encoded[offset + 1]);
}
/**
* Encodes given sequence of nibbles into a sequence of octets.
*
* @param encoded the nibbles to decode.
*
* @return the encoded octets.
*/
protected static byte[] decodeMultiple(final byte[] encoded) {
if (encoded == null) {
throw new IllegalArgumentException("null encoded");
}
if ((encoded.length & 0x01) == 0x01) {
throw new IllegalArgumentException(
"encoded.length(" + encoded.length + ") is not even");
}
final byte[] decoded = new byte[encoded.length >> 1];
int offset = 0;
for (int i = 0; i < decoded.length; i++) {
decoded[i] = (byte) decodeSingle(encoded, offset);
offset += 2;
}
return decoded;
}
/**
* Decodes given sequence of nibbles into a sequence of octets.
*
* @param encoded the nibbles to decode.
*
* @return the decoded octets.
*/
public byte[] decode(final byte[] encoded) {
return decodeMultiple(encoded);
}
Esta es una manera muy rápida. No se necesitan bibliotecas externas.
final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray();
public static String encodeHexString( byte[] bytes ) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEXARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F];
}
return new String(hexChars);
}
No pude entender exactamente qué querías decir con byte String, pero aquí hay algunas conversiones de byte a String y viceversa, por supuesto, hay mucho más en las documentaciones oficiales.
Integer intValue = 149;
El valor del byte correspondiente es:
Byte byteValue = intValue.byteValue(); // this will convert the rightmost byte of the intValue to byte, because Byte is an 8 bit object and Integer is at least 16 bit, and it will give you a signed number in this case -107
recuperar el valor entero de una variable Byte:
Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer
Desde Byte e Integer hasta la cadena hexadecimal:
esta es la forma en que lo hago:
Integer anInt = 149
Byte aByte = anInt.byteValue();
String hexFromInt = "".format("0x%x", anInt); // This will output 0x95
String hexFromByte = "".format("0x%x", aByte); // This will output 0x95
Conversión de una matriz de bytes en una cadena hexadecimal: por
lo que sé, no existe una función simple para convertir todos los elementos dentro de una matriz de algunos Object
en elementos de otro Object
, por lo que debe hacerlo usted mismo. Puede usar las siguientes funciones:
Del byte [] a String:
public static String byteArrayToHexString(byte[] byteArray){
String hexString = "";
for(int i = 0; i < byteArray.length; i++){
String thisByte = "".format("%x", byteArray[i]);
hexString += thisByte;
}
return hexString;
}
Y de la cadena hexadecimal al byte []:
public static byte[] hexStringToByteArray(String hexString){
byte[] bytes = new byte[hexString.length() / 2];
for(int i = 0; i < hexString.length(); i += 2){
String sub = hexString.substring(i, i + 2);
Integer intVal = Integer.parseInt(sub, 16);
bytes[i / 2] = intVal.byteValue();
String hex = "".format("0x%x", bytes[i / 2]);
}
return bytes;
}
Es demasiado tarde pero espero que esto pueda ayudar a otros;)
Ahí está tu método rápido:
private static final String[] hexes = new String[]{
"00","01","02","03","04","05","06","07","08","09","0A","0B","0C","0D","0E","0F",
"10","11","12","13","14","15","16","17","18","19","1A","1B","1C","1D","1E","1F",
"20","21","22","23","24","25","26","27","28","29","2A","2B","2C","2D","2E","2F",
"30","31","32","33","34","35","36","37","38","39","3A","3B","3C","3D","3E","3F",
"40","41","42","43","44","45","46","47","48","49","4A","4B","4C","4D","4E","4F",
"50","51","52","53","54","55","56","57","58","59","5A","5B","5C","5D","5E","5F",
"60","61","62","63","64","65","66","67","68","69","6A","6B","6C","6D","6E","6F",
"70","71","72","73","74","75","76","77","78","79","7A","7B","7C","7D","7E","7F",
"80","81","82","83","84","85","86","87","88","89","8A","8B","8C","8D","8E","8F",
"90","91","92","93","94","95","96","97","98","99","9A","9B","9C","9D","9E","9F",
"A0","A1","A2","A3","A4","A5","A6","A7","A8","A9","AA","AB","AC","AD","AE","AF",
"B0","B1","B2","B3","B4","B5","B6","B7","B8","B9","BA","BB","BC","BD","BE","BF",
"C0","C1","C2","C3","C4","C5","C6","C7","C8","C9","CA","CB","CC","CD","CE","CF",
"D0","D1","D2","D3","D4","D5","D6","D7","D8","D9","DA","DB","DC","DD","DE","DF",
"E0","E1","E2","E3","E4","E5","E6","E7","E8","E9","EA","EB","EC","ED","EE","EF",
"F0","F1","F2","F3","F4","F5","F6","F7","F8","F9","FA","FB","FC","FD","FE","FF"
};
public static String byteToHex(byte b) {
return hexes[b&0xFF];
}
Al igual que algunas otras respuestas, recomiendo usar String.format()
y BigInteger
. Pero para interpretar la matriz de bytes como una representación binaria big-endian en lugar de una representación binaria del complemento a dos (con signum y uso incompleto del posible rango de valores hexadecimales) use BigInteger (int signum, byte [] magnitud) , no BigInteger (byte [] val ) .
Por ejemplo, para una matriz de bytes de longitud 8 use:
String.format("%016X", new BigInteger(1,bytes))
Ventajas:
Desventaja:
Ejemplo:
byte[] bytes = new byte[8];
Random r = new Random();
System.out.println("big-endian | two's-complement");
System.out.println("-----------------|-----------------");
for (int i = 0; i < 10; i++) {
r.nextBytes(bytes);
System.out.print(String.format("%016X", new BigInteger(1,bytes)));
System.out.print(" | ");
System.out.print(String.format("%016X", new BigInteger(bytes)));
System.out.println();
}
Salida de ejemplo:
big-endian | two's-complement
-----------------|-----------------
3971B56BC7C80590 | 3971B56BC7C80590
64D3C133C86CCBDC | 64D3C133C86CCBDC
B232EFD5BC40FA61 | -4DCD102A43BF059F
CD350CC7DF7C9731 | -32CAF338208368CF
82CDC9ECC1BC8EED | -7D3236133E437113
F438C8C34911A7F5 | -BC7373CB6EE580B
5E99738BE6ACE798 | 5E99738BE6ACE798
A565FE5CE43AA8DD | -5A9A01A31BC55723
032EBA783D2E9A9F | 032EBA783D2E9A9F
8FDAA07263217ABA | -70255F8D9CDE8546