texto online hexadecimal convertir java bytearray hex

online - ¿Cómo convertir una matriz de bytes a una cadena hexadecimal en Java?



java to hexadecimal (22)

Tengo una matriz de bytes llena de números hexadecimales e imprimirla de manera fácil es bastante inútil porque hay muchos elementos no imprimibles. Lo que necesito es el código hexadecimal exacto en la forma de: 3a5f771c


¿Qué tal esto?

String byteToHex(final byte[] hash) { Formatter formatter = new Formatter(); for (byte b : hash) { formatter.format("%02x", b); } String result = formatter.toString(); formatter.close(); return result; }


// Desplazar bytes es más eficiente // Puedes usar este también

public static String getHexString (String s) { byte[] buf = s.getBytes(); StringBuffer sb = new StringBuffer(); for (byte b:buf) { sb.append(String.format("%x", b)); } return sb.toString(); }


Al menor costo de almacenar la tabla de búsqueda, esta implementación es simple y muy rápida.

private static final char[] BYTE2HEX=( "000102030405060708090A0B0C0D0E0F"+ "101112131415161718191A1B1C1D1E1F"+ "202122232425262728292A2B2C2D2E2F"+ "303132333435363738393A3B3C3D3E3F"+ "404142434445464748494A4B4C4D4E4F"+ "505152535455565758595A5B5C5D5E5F"+ "606162636465666768696A6B6C6D6E6F"+ "707172737475767778797A7B7C7D7E7F"+ "808182838485868788898A8B8C8D8E8F"+ "909192939495969798999A9B9C9D9E9F"+ "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+ "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+ "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+ "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+ "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+ "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray(); ; public static String getHexString(byte[] bytes) { final int len=bytes.length; final char[] chars=new char[len<<1]; int hexIndex; int idx=0; int ofs=0; while (ofs<len) { hexIndex=(bytes[ofs++] & 0xFF)<<1; chars[idx++]=BYTE2HEX[hexIndex++]; chars[idx++]=BYTE2HEX[hexIndex]; } return new String(chars); }


Aquí hay una implementación de tipo java.util.Base64 (parcial), ¿no es bonita?

public class Base16/*a.k.a. Hex*/ { public static class Encoder{ private static char[] toLowerHex={''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'',''a'',''b'',''c'',''d'',''e'',''f''}; private static char[] toUpperHex={''0'',''1'',''2'',''3'',''4'',''5'',''6'',''7'',''8'',''9'',''A'',''B'',''C'',''D'',''E'',''F''}; private boolean upper; public Encoder(boolean upper) { this.upper=upper; } public String encode(byte[] data){ char[] value=new char[data.length*2]; char[] toHex=upper?toUpperHex:toLowerHex; for(int i=0,j=0;i<data.length;i++){ int octet=data[i]&0xFF; value[j++]=toHex[octet>>4]; value[j++]=toHex[octet&0xF]; } return new String(value); } static final Encoder LOWER=new Encoder(false); static final Encoder UPPER=new Encoder(true); } public static Encoder getEncoder(){ return Encoder.LOWER; } public static Encoder getUpperEncoder(){ return Encoder.UPPER; } //... }


De acuerdo, hay muchas maneras de hacerlo, pero si decide utilizar una biblioteca, sugeriría buscar en su proyecto para ver si se ha implementado algo en una biblioteca que ya forma parte de su proyecto antes de agregar una nueva. Sólo para hacer esto. Por ejemplo si no tienes ya

org.apache.commons.codec.binary.Hex

tal vez usted tiene ...

org.apache.xerces.impl.dv.util.HexBin


De la discusión here , y especialmente de this respuesta, esta es la función que actualmente uso:

private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(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); }

Mis propios pequeños puntos de referencia (un millón de bytes mil veces, 256 bytes 10 millones de veces) demostraron que era mucho más rápido que cualquier otra alternativa, aproximadamente la mitad de las veces en arreglos largos. Comparado con la respuesta de la que lo tomé, cambiar a operaciones a nivel de bits (como se sugiere en la discusión), recortar un 20% del tiempo para arreglos largos. (Edit: cuando digo que es más rápido que las alternativas, me refiero al código alternativo ofrecido en las discusiones. El rendimiento es equivalente al de Commons Codec, que utiliza un código muy similar).


Este simple oneliner funciona para mi
String result = new BigInteger(1, inputBytes).toString(16);
EDITAR: el uso de esto eliminará los ceros iniciales, pero funcionó para mi caso de uso. Gracias @Voicu por señalarlo


He encontrado tres formas diferentes aquí: http://www.rgagnon.com/javadetails/java-0596.html

El más elegante, como él también señala, creo que es este:

static final String HEXES = "0123456789ABCDEF"; public static String getHex( byte [] raw ) { if ( raw == null ) { return null; } 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(); }


La biblioteca Apache Commons Codec tiene una clase Hex para realizar este tipo de trabajo.

import org.apache.commons.codec.binary.Hex; String foo = "I am a string"; byte[] bytes = foo.getBytes(); System.out.println( Hex.encodeHexString( bytes ) );


La solución más simple, sin librerías externas, sin constantes de dígitos:

public static String byteArrayToHex(byte[] a) { StringBuilder sb = new StringBuilder(a.length * 2); for(byte b: a) sb.append(String.format("%02x", b)); return sb.toString(); }


Mi solución se basa en la solución de quizás WeCouldStealAVan, pero no se basa en ninguna tabla de búsqueda asignada adicionalmente. No utiliza ningún hacks de ''int-to-char'' (en realidad, Character.forDigit() hace, realizando una comparación para verificar cuál es realmente el dígito) y, por lo tanto, podría ser un poco más lento. Por favor, siéntase libre de usarlo donde quiera. Aclamaciones.

public static String bytesToHex(final byte[] bytes) { final int numBytes = bytes.length; final char[] container = new char[numBytes * 2]; for (int i = 0; i < numBytes; i++) { final int b = bytes[i] & 0xFF; container[i * 2] = Character.forDigit(b >>> 4, 0x10); container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10); } return new String(container); }


No puedo encontrar ninguna solución en esta página que no

  1. Usa un lazo
  2. Use javax.xml.bind.DatatypeConverter que compila bien pero a menudo lanza java.lang.NoClassDefFoundError en tiempo de ejecución.

Aquí hay una solución que no tiene las fallas anteriores (aunque no hay promesas, la mía no tiene otras fallas)

import java.math.BigInteger; import static java.lang.System.out; public final class App2 { // | proposed solution. public static String encode(byte[] bytes) { final int length = bytes.length; // | BigInteger constructor throws if it is given an empty array. if (length == 0) { return "00"; } final int evenLength = (int)(2 * Math.ceil(length / 2.0)); final String format = "%0" + evenLength + "x"; final String result = String.format (format, new BigInteger(bytes)); return result; } public static void main(String[] args) throws Exception { // 00 out.println(encode(new byte[] {})); // 01 out.println(encode(new byte[] {1})); //203040 out.println(encode(new byte[] {0x20, 0x30, 0x40})); // 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e out.println(encode("All your base are belong to us.".getBytes())); } }

No podría obtener esto bajo 62 códigos de operación, pero si puede vivir sin 0 rellenos en caso de que el primer byte sea menor que 0x10, entonces la siguiente solución solo usa 23 códigos de operación. Realmente muestra cómo las soluciones "fáciles de implementar" como "pad con un cero si la longitud de la cadena es impar" pueden ser bastante caras si una implementación nativa no está disponible (o en este caso, si BigInteger tenía la opción de prefijo con ceros) Encadenar).

public static String encode(byte[] bytes) { final int length = bytes.length; // | BigInteger constructor throws if it is given an empty array. if (length == 0) { return "00"; } return new BigInteger(bytes).toString(16); }


Prefiero usar esto:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes, int offset, int count) { char[] hexChars = new char[count * 2]; for ( int j = 0; j < count; j++ ) { int v = bytes[j+offset] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); }

Es una adaptación ligeramente más flexible de la respuesta aceptada. Personalmente, mantengo la respuesta aceptada y esta sobrecarga junto con ella, utilizable en más contextos.


Si está buscando una matriz de bytes exactamente como esta para Python, he convertido esta implementación de Java en Python.

class ByteArray: @classmethod def char(cls, args=[]): cls.hexArray = "0123456789ABCDEF".encode(''utf-16'') j = 0 length = (cls.hexArray) if j < length: v = j & 0xFF hexChars = [None, None] hexChars[j * 2] = str( cls.hexArray) + str(v) hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F) # Use if you want... #hexChars.pop() return str(hexChars) array = ByteArray() print array.char(args=[])


Una pequeña variante de la solución propuesta por @maybewecouldstealavan, que le permite agrupar visualmente N bytes en la cadena hex de salida:

final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray(); final static char BUNDLE_SEP = '' ''; public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) { char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)]; for (int j = 0, k = 1; j < bytes.length; j++, k++) { int v = bytes[j] & 0xFF; int start = (j * 2) + j/bundleSize; hexChars[start] = HEX_ARRAY[v >>> 4]; hexChars[start + 1] = HEX_ARRAY[v & 0x0F]; if ((k % bundleSize) == 0) { hexChars[start + 2] = BUNDLE_SEP; } } return new String(hexChars).trim(); }

Es decir:

bytesToHexString("..DOOM..".toCharArray().getBytes(), 2); 2E2E 444F 4F4D 2E2E bytesToHexString("..DOOM..".toCharArray().getBytes(), 4); 2E2E444F 4F4D2E2E


Una solución de guayaba, para completar:

import com.google.common.io.BaseEncoding; ... byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8); final String hex = BaseEncoding.base16().lowerCase().encode(bytes);

Ahora, el hex es "48656c6c6f20776f726c64" .


Use la clase DataTypeConverter javax.xml.bind.DataTypeConverter

String hexString = DatatypeConverter.printHexBinary(bytes[] raw);


Usualmente uso el siguiente método para la declaración debuf, pero no sé si es la mejor manera de hacerlo o no

private static String digits = "0123456789abcdef"; public static String toHex(byte[] data){ StringBuffer buf = new StringBuffer(); for (int i = 0; i != data.length; i++) { int v = data[i] & 0xff; buf.append(digits.charAt(v >> 4)); buf.append(digits.charAt(v & 0xf)); } return buf.toString(); }


Utilice DatatypeConverter.printHexBinary() . Puede leer su documentación en javax.xml.bind.DataTypeConverter

Por ejemplo:

byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61}; System.out.println(javax.xml.bind.DatatypeConverter.printHexBinary(bytes));

Resultará en:

000086003D

Como puede ver, esto recuperará la cadena hexadecimal que representa la matriz de bytes con ceros iniciales.

Esta respuesta es básicamente la misma que en la pregunta En Java, ¿cómo convierto una matriz de bytes a una cadena de dígitos hexadecimales mientras mantengo los ceros iniciales?


Yo usaría algo como esto para longitud fija, como hashes:

md5sum = String.format("%032x", new BigInteger(1, md.digest()));


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


private static String bytesToHexString(byte[] bytes, int length) { if (bytes == null || length == 0) return null; StringBuilder ret = new StringBuilder(2*length); for (int i = 0 ; i < length ; i++) { int b; b = 0x0f & (bytes[i] >> 4); ret.append("0123456789abcdef".charAt(b)); b = 0x0f & bytes[i]; ret.append("0123456789abcdef".charAt(b)); } return ret.toString(); }