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 forma de:3a5f771c
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 forma de:3a5f771c
Respuestas:
De la discusión aquí , y especialmente esta respuesta, esta es la función que uso actualmente:
private static final char[] HEX_ARRAY = "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] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
Mis propios puntos de referencia pequeños (un millón de bytes mil veces, 256 bytes 10 millones de veces) demostraron que es mucho más rápido que cualquier otra alternativa, aproximadamente la mitad del tiempo en matrices largas. En comparación con la respuesta que obtuve, cambiar a operaciones bit a bit, como se sugirió en la discusión, redujo aproximadamente un 20% del tiempo para las matrices largas. (Editar: cuando digo que es más rápido que las alternativas, me refiero al código alternativo que se ofrece en las discusiones. El rendimiento es equivalente a Commons Codec, que usa un código muy similar).
Versión 2k20, con respecto a las cadenas compactas de Java 9:
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}
String printHexBinary(byte[])
y byte[] parseHexBinary(String)
. printHexBinary
es, sin embargo, mucho (2x) más lento que la función en esta respuesta. (Verifiqué la fuente; usa a stringBuilder
. parseHexBinary
Usa una matriz.) Realmente, sin embargo, para la mayoría de los propósitos es lo suficientemente rápido y probablemente ya lo tenga.
printHexBinary
?
javax.xml.bind.DataTypeConverter
está siendo eliminado de Java 11.
La biblioteca de códecs de Apache Commons tiene una clase Hex para hacer 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 ) );
import org.apache.commons.codec.*;
usted podría hacerloimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
con este método:String toHexString(byte[] data)
El método javax.xml.bind.DatatypeConverter.printHexBinary()
, parte de la Arquitectura Java para Enlace XML (JAXB) , era una forma conveniente de convertir una byte[]
cadena hexadecimal. La DatatypeConverter
clase también incluyó muchos otros métodos útiles de manipulación de datos.
En Java 8 y versiones anteriores, JAXB era parte de la biblioteca estándar de Java. Se desaprobó con Java 9 y se eliminó con Java 11 , como parte de un esfuerzo por mover todos los paquetes Java EE a sus propias bibliotecas. Es una larga historia . Ahora, javax.xml.bind
no existe, y si desea utilizar JAXB, que contiene DatatypeConverter
, deberá instalar la API JAXB y JAXB Runtime de Maven.
Ejemplo de uso:
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
Resultará en:
000086003D
Esta respuesta es la misma que esta .
La solución más simple, sin libs 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();
}
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 hex
es "48656c6c6f20776f726c64"
.
new HashCode(bytes).toString()
.
HashCode.fromBytes(checksum).toString()
Este simple oneliner funciona para mí
String result = new BigInteger(1, inputBytes).toString(16);
EDITAR: usar esto eliminará los ceros iniciales, pero hey funcionó para mi caso de uso. Gracias @Voicu por señalarlo
Aquí hay algunas opciones comunes ordenadas desde simples (una línea) hasta complejas (gran biblioteca). Si está interesado en el rendimiento, vea los micro puntos de referencia a continuación.
Una solución muy simple es usar la BigInteger
representación hexadecimal de:
new BigInteger(1, someByteArray).toString(16)
Tenga en cuenta que dado que esto maneja números que no son cadenas de bytes arbitrarias , omitirá los ceros a la izquierda; esto puede o no ser lo que desea (por ejemplo, 000AE3
vs 0AE3
para una entrada de 3 bytes). Esto también es muy lento, aproximadamente 100 veces más lento en comparación con la siguiente opción.
Aquí hay un fragmento de código completo, copiable y pegable que admite mayúsculas / minúsculas y endianness . Está optimizado para minimizar la complejidad de la memoria y maximizar el rendimiento y debería ser compatible con todas las versiones modernas de Java (5+).
private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {
// our output size will be exactly 2x byte-array length
final char[] buffer = new char[byteArray.length * 2];
// choose lower or uppercase lookup table
final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;
int index;
for (int i = 0; i < byteArray.length; i++) {
// for little endian we count from last to first
index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;
// extract the upper 4 bit and look up char (0-A)
buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
// extract the lower 4 bit and look up char (0-A)
buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
}
return new String(buffer);
}
public static String encode(byte[] byteArray) {
return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}
El código fuente completo con licencia Apache v2 y decodificador se puede encontrar aquí .
Mientras trabajaba en mi proyecto anterior, creé este pequeño kit de herramientas para trabajar con bytes en Java. No tiene dependencias externas y es compatible con Java 7+. Incluye, entre otros, un decodificador / decodificador HEX muy rápido y bien probado:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Puedes verlo en Github: bytes-java .
Por supuesto, están los buenos códecs comunes . ( opinión de advertencia más adelante ) Mientras trabajaba en el proyecto descrito anteriormente, analicé el código y me decepcionó bastante; una gran cantidad de códigos no organizados duplicados, códecs obsoletos y exóticos probablemente solo sean útiles para muy pocas implementaciones muy complejas y lentas de códecs populares (específicamente Base64). Por lo tanto, tomaría una decisión informada si desea utilizarla o una alternativa. De todos modos, si todavía quieres usarlo, aquí hay un fragmento de código:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
La mayoría de las veces ya tienes a la guayaba como dependencia. Si es así, solo use:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Si usa Spring Framework con Spring Security , puede usar lo siguiente:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Si ya usa el marco de seguridad Bouncy Castle , puede usar su utilidad Hex
:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
En versiones anteriores de Java (8 y posteriores), el código Java para JAXB se incluía como dependencia de tiempo de ejecución. Desde Java 9 y la modularización de Jigsaw, su código no puede acceder a otro código fuera de su módulo sin una declaración explícita. Así que tenga en cuenta si obtiene una excepción como:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
cuando se ejecuta en una JVM con Java 9+. Si es así, cambie las implementaciones a cualquiera de las alternativas anteriores. Ver también esta pregunta .
Estos son los resultados de una simple referencia de micro JMH que codifica conjuntos de bytes de diferentes tamaños . Los valores son operaciones por segundo, por lo que mayor es mejor. Tenga en cuenta que los micro puntos de referencia a menudo no representan el comportamiento del mundo real, por lo tanto, tome estos resultados con un grano de sal.
| Name (ops/s) | 16 byte | 32 byte | 128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger | 2,088,514 | 1,008,357 | 133,665 | 4 |
| Opt2/3: Bytes Lib | 20,423,170 | 16,049,841 | 6,685,522 | 825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 | 529 |
| Opt5: Guava | 10,177,925 | 6,937,833 | 2,094,658 | 257 |
| Opt6: Spring | 18,704,986 | 13,643,374 | 4,904,805 | 601 |
| Opt7: BC | 7,501,666 | 3,674,422 | 1,077,236 | 152 |
| Opt8: JAX-B | 13,497,736 | 8,312,834 | 2,590,940 | 346 |
Especificaciones: JDK 8u202, i7-7700K, Win10, 24GB Ram. Vea el punto de referencia completo aquí .
Utilice la clase DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Usaría algo como esto para una longitud fija, como hashes:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Encontré 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();
}
if (raw == null) return null
No es fallar rápido. ¿Por qué usarías alguna vez una null
llave?
Con el 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);
}
BYTE2HEX
matriz con un for
ciclo simple ?
static { }
bloque.
¿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;
}
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.
Usualmente uso el siguiente método para la declaración de 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();
}
StringBuilder buf = new StringBuilder(data.length * 2);
.
De acuerdo, hay muchas maneras de hacer esto, pero si decides usar una biblioteca, te sugiero que analices tu proyecto para ver si algo se ha implementado en una biblioteca que ya forma parte de tu proyecto antes de agregar una nueva biblioteca solo para hacer esto. Por ejemplo si aún no tienes
org.apache.commons.codec.binary.Hex
tal vez tienes ...
org.apache.xerces.impl.dv.util.HexBin
Si está utilizando el marco de Spring Security, puede usar:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
Agregar una jarra de utilidad para una función simple no es una buena opción. En su lugar, reúna sus propias clases de utilidad. lo siguiente es posible una implementación más rápida.
public class ByteHex {
public static int hexToByte(char ch) {
if ('0' <= ch && ch <= '9') return ch - '0';
if ('A' <= ch && ch <= 'F') return ch - 'A' + 10;
if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
return -1;
}
private static final String[] byteToHexTable = 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"
};
private static final String[] byteToHexTableLowerCase = 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 byteToHexTable[b & 0xFF];
}
public static String byteToHex(byte[] bytes){
if(bytes == null) return null;
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
return sb.toString();
}
public static String byteToHex(short[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
return sb.toString();
}
public static String byteToHexLowerCase(byte[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
return sb.toString();
}
public static byte[] hexToByte(String hexString) {
if(hexString == null) return null;
byte[] byteArray = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
}
return byteArray;
}
public static byte hexPairToByte(char ch1, char ch2) {
return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
}
}
Una pequeña variante de la solución propuesta por @maybewecouldstealavan, que le permite agrupar visualmente N bytes en la cadena hexadecimal 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
No puedo encontrar ninguna solución en esta página que no
Aquí hay una solución que no tiene los defectos anteriores (sin promesas, la mía no tiene otros defectos)
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 pude obtener esto con 62 códigos de operación, pero si puedes vivir sin relleno 0 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 usted mismo" como "pad con un cero si la longitud de la cadena es impar" pueden ser bastante costosas si una implementación nativa no está disponible (o en este caso, si BigInteger tenía la opción de prefijar con ceros en 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);
}
Mi solución se basa en la solución maybeWeCouldStealAVan, pero no se basa en ninguna tabla de búsqueda asignada adicionalmente. No utiliza ningún truco de conversión de 'int-to-char' (en realidad, lo Character.forDigit()
hace, realizando alguna 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. Salud.
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);
}
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=[])
Aquí hay una java.util.Base64
implementación similar (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;
}
//...
}
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();
}
Converts bytes data to hex characters
@param bytes byte array to be converted to hex string
@return byte String in hex format
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
toHexString(...)
método que puede ayudar si esto es lo que estás buscando. TambiénString.format(...)
puede hacer algunos trucos de formateo con la%2x
cadena de código.