Ho un array di byte riempito con numeri esadecimali e stamparlo in modo semplice è abbastanza inutile perché ci sono molti elementi non stampabili. Quello di cui ho bisogno è l'esatto codice esadecimale sotto forma di:3a5f771c
Ho un array di byte riempito con numeri esadecimali e stamparlo in modo semplice è abbastanza inutile perché ci sono molti elementi non stampabili. Quello di cui ho bisogno è l'esatto codice esadecimale sotto forma di:3a5f771c
Risposte:
Dalla discussione qui , e soprattutto questa risposta, questa è la funzione che attualmente uso:
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);
}
I miei piccoli benchmark (un milione di byte mille volte, 256 byte 10 milioni di volte) hanno dimostrato che è molto più veloce di qualsiasi altra alternativa, circa la metà del tempo su array lunghi. Rispetto alla risposta da cui l'ho presa, passando a operazioni bit per bit --- come suggerito nella discussione --- ha ridotto del 20% circa il tempo per le lunghe matrici. (Modifica: quando dico che è più veloce delle alternative, intendo il codice alternativo offerto nelle discussioni. Le prestazioni sono equivalenti a Commons Codec, che utilizza un codice molto simile.)
Versione 2k20, rispetto alle stringhe compatte 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[])
e byte[] parseHexBinary(String)
. printHexBinary
è, tuttavia, molto (2x) più lento della funzione in questa risposta. (Ho controllato la fonte; usa un stringBuilder
. parseHexBinary
Usa un array.) In realtà, però, per la maggior parte degli scopi è abbastanza veloce e probabilmente lo hai già.
printHexBinary
?
javax.xml.bind.DataTypeConverter
viene rimosso da Java 11.
La libreria Codec di Apache Commons ha una classe Hex per fare proprio questo tipo di lavoro.
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.*;
tuo potresti fareimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
String toHexString(byte[] data)
Il metodo javax.xml.bind.DatatypeConverter.printHexBinary()
, parte di Java Architecture for XML Binding (JAXB) , era un modo conveniente per convertire una byte[]
stringa esadecimale. La DatatypeConverter
classe includeva anche molti altri utili metodi di manipolazione dei dati.
In Java 8 e precedenti, JAXB faceva parte della libreria standard Java. È stato deprecato con Java 9 e rimosso con Java 11 , come parte dello sforzo di spostare tutti i pacchetti Java EE nelle proprie librerie. È una lunga storia . Ora javax.xml.bind
non esiste e se si desidera utilizzare JAXB, che contiene DatatypeConverter
, è necessario installare l' API JAXB e JAXB Runtime da Maven.
Esempio di utilizzo:
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
Si tradurrà in:
000086003D
Questa risposta è uguale a questa .
Soluzione più semplice, nessuna libreria esterna, nessuna costante di cifre:
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 soluzione Guava, per completezza:
import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);
Adesso lo hex
è "48656c6c6f20776f726c64"
.
new HashCode(bytes).toString()
.
HashCode.fromBytes(checksum).toString()
Questo semplice oneliner funziona per me
String result = new BigInteger(1, inputBytes).toString(16);
EDIT: l'uso di questo rimuoverà gli zeri iniziali, ma ha funzionato per il mio caso d'uso. Grazie @Voicu per averlo segnalato
Ecco alcune opzioni comuni ordinate dal semplice (one-liner) al complesso (enorme libreria). Se sei interessato alle prestazioni, consulta i micro benchmark di seguito.
Una soluzione molto semplice è quella di utilizzare la BigInteger
rappresentazione esadecimale:
new BigInteger(1, someByteArray).toString(16)
Si noti che poiché gestisce numeri non stringhe di byte arbitrarie , ometterà gli zeri iniziali - questo potrebbe essere o meno ciò che si desidera (ad es. 000AE3
Vs 0AE3
per un input di 3 byte). Anche questo è molto lento, circa 100 volte più lento rispetto alla prossima opzione.
Ecco uno snippet di codice completo, copia e incollabile che supporta maiuscolo / minuscolo e endianness . È ottimizzato per minimizzare la complessità della memoria e massimizzare le prestazioni e dovrebbe essere compatibile con tutte le moderne versioni di 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);
}
Il codice sorgente completo con licenza e decoder Apache v2 è disponibile qui .
Mentre lavoravo al mio precedente progetto, ho creato questo piccolo toolkit per lavorare con byte in Java. Non ha dipendenze esterne ed è compatibile con Java 7+. Include, tra gli altri, un en / decoder HEX molto veloce e ben collaudato:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Puoi verificarlo su Github: bytes-java .
Naturalmente ci sono i buoni vecchi codec comuni . ( avviso di avviso in anticipo ) Mentre stavo lavorando al progetto descritto sopra ho analizzato il codice e sono rimasto piuttosto deluso; molti duplicati di codice non organizzato, codec obsoleti ed esotici probabilmente utili solo per pochissime e abbastanza ingegnerizzate e lente implementazioni di codec popolari (in particolare Base64). Pertanto, prenderei una decisione informata se desideri utilizzarla o un'alternativa. Comunque, se vuoi ancora usarlo, ecco uno snippet di codice:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
Molto spesso hai già Guava come dipendenza. In tal caso basta usare:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Se si utilizza il framework Spring con Spring Security è possibile utilizzare quanto segue:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Se usi già il framework di sicurezza Bouncy Castle puoi usare il suo Hex
util:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
Nelle precedenti versioni Java (8 e precedenti) il codice Java per JAXB era incluso come dipendenza del runtime. Poiché la modularizzazione di Java 9 e Jigsaw, il codice non può accedere ad altro codice al di fuori del modulo senza una dichiarazione esplicita. Quindi fai attenzione se ricevi un'eccezione come:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
durante l'esecuzione su una JVM con Java 9+. In tal caso, passa alle implementazioni in una delle alternative sopra. Vedi anche questa domanda .
Ecco i risultati di un semplice micro benchmark JMH che codifica array di byte di dimensioni diverse . I valori sono operazioni al secondo, quindi maggiore è meglio. Nota che i micro benchmark molto spesso non rappresentano il comportamento del mondo reale, quindi prendi questi risultati con un granello di sale.
| 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 |
Specifiche: JDK 8u202, i7-7700K, Win10, 24GB Ram. Vedi il benchmark completo qui .
Utilizzare la classe DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Vorrei usare qualcosa del genere per una lunghezza fissa, come gli hash:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Ho trovato tre modi diversi qui: http://www.rgagnon.com/javadetails/java-0596.html
Il più elegante, come osserva anche, penso sia questo:
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
non fallisce velocemente. Perché mai dovresti usare una null
chiave?
A un costo minore di memorizzazione della tabella di ricerca questa implementazione è semplice e molto veloce.
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
array con un semplice for
ciclo?
static { }
blocco.
Cosa ne pensi di questo?
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;
}
Non è necessario utilizzare alcuna libreria esterna o scrivere codice basato su loop e costanti.
Basta solo questo:
byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);
Preferisco usare questo:
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);
}
È un adattamento leggermente più flessibile della risposta accettata. Personalmente, mantengo insieme sia la risposta accettata che questo sovraccarico, utilizzabile in più contesti.
Di solito uso il seguente metodo per la dichiarazione debuf, ma non so se sia il modo migliore per farlo o meno
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);
.
Ok, ci sono molti modi per farlo, ma se decidi di usare una libreria ti suggerirei di cercare nel tuo progetto per vedere se qualcosa è stato implementato in una libreria che è già parte del tuo progetto prima di aggiungere una nuova libreria solo per fare questo. Ad esempio se non lo hai già fatto
org.apache.commons.codec.binary.Hex
forse hai ...
org.apache.xerces.impl.dv.util.HexBin
Se si utilizza il framework Spring Security, è possibile utilizzare:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
L'aggiunta di un jar di utilità per una funzione semplice non è una buona opzione. Invece assemblare le proprie classi di utilità. di seguito è possibile un'implementazione più rapida.
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 piccola variante della soluzione proposta da @maybewecouldstealavan, che consente di raggruppare visivamente N byte nella stringa esadecimale di output:
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();
}
Questo è:
bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E
bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E
Non riesco a trovare alcuna soluzione in questa pagina che non lo fa
Ecco una soluzione che non ha i difetti sopra (nessuna promessa la mia non ha altri difetti però)
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()));
}
}
Non sono riuscito a ottenere questo con 62 codici operativi, ma se riesci a vivere senza 0 padding nel caso in cui il primo byte sia inferiore a 0x10, la seguente soluzione utilizza solo 23 codici operativi. Mostra davvero come le soluzioni "facili da implementare" come "pad con uno zero se la lunghezza della stringa è dispari" possono diventare piuttosto costose se un'implementazione nativa non è già disponibile (o in questo caso, se BigInteger aveva un'opzione per il prefisso con zeri in accordare).
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);
}
La mia soluzione si basa sulla soluzione di forse WeCouldStealAVan, ma non si basa su alcuna tabella di ricerca allocata in aggiunta. Non utilizza alcun hack di cast "int-to-char" (in realtà, lo Character.forDigit()
fa, eseguendo alcuni confronti per verificare quale sia veramente la cifra) e quindi potrebbe essere un po 'più lento. Sentiti libero di usarlo dove vuoi. Saluti.
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);
}
Se stai cercando un array di byte esattamente come questo per Python, ho convertito questa implementazione Java in 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=[])
Ecco java.util.Base64
un'implementazione simile (parziale), non è carina?
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(...)
metodo che può aiutare se questo è quello che stai cercando. Inoltre, èString.format(...)
possibile eseguire alcuni trucchi di formattazione utilizzando la%2x
stringa di codice.