Ho una matrice di byte. Voglio che ogni stringa di byte di quell'array sia convertita nei corrispondenti valori esadecimali.
Esiste una funzione in Java per convertire un array di byte in esadecimale?
Ho una matrice di byte. Voglio che ogni stringa di byte di quell'array sia convertita nei corrispondenti valori esadecimali.
Esiste una funzione in Java per convertire un array di byte in esadecimale?
Risposte:
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
sintassi
%[flags][width]conversion
'0'
: il risultato sarà a zero2
'X'
: il risultato è formattato come intero esadecimale, maiuscoloGuardando il testo della domanda, è anche possibile che questo sia ciò che viene richiesto:
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]"
Qui vengono utilizzate diverse risposte Integer.toHexString(int)
; questo è fattibile, ma con alcuni avvertimenti. Poiché il parametro è un int
, viene eseguita una conversione primitiva allargata byte
all'argomento, che comporta l'estensione del segno.
byte b = -1;
System.out.println(Integer.toHexString(b));
// prints "ffffffff"
L'8 bit byte
, che è firmato in Java, è esteso a 32 bit int
. Per annullare efficacemente questa estensione di segno, si può mascherare byte
con 0xFF
.
byte b = -1;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "ff"
Un altro problema con l'utilizzo toHexString
è che non si riempie di zero:
byte b = 10;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "a"
Entrambi i fattori combinati dovrebbero rendere la String.format
soluzione più preferibile.
byte
, da -128
a 127
, compresotoHexString
. Devi mascherarlo con & 0xFF
, cioè lo Integer.toHexString(-46 & 0xFF)
è "d2"
.
byte
valore & 0xFF
ogni volta. la format
soluzione sopra potrebbe richiedere anche il mascheramento a seconda di cosa stai effettivamente usando come argomento.
Sto postando perché nessuna delle risposte esistenti spiega perché i loro approcci funzionano, cosa che penso sia davvero importante per questo problema. In alcuni casi, ciò fa apparire la soluzione proposta inutilmente complicata e sottile. Per illustrare fornirò un approccio abbastanza semplice, ma fornirò un po 'più di dettagli per aiutare a illustrare il motivo per cui funziona.
Prima di tutto, cosa stiamo cercando di fare? Vogliamo convertire un valore di byte (o un array di byte) in una stringa che rappresenta un valore esadecimale in ASCII. Quindi il primo passo è scoprire esattamente cos'è un byte in Java:
Il tipo di dati byte è un intero di complemento a due bit con segno a 8 bit . Ha un valore minimo di -128 e un valore massimo di 127 (incluso). Il tipo di dati byte può essere utile per salvare la memoria in array di grandi dimensioni, dove il risparmio di memoria conta davvero. Possono anche essere usati al posto di int dove i loro limiti aiutano a chiarire il tuo codice; il fatto che l'intervallo di una variabile sia limitato può servire come una forma di documentazione.
Cosa significa questo? Alcune cose: prima di tutto, significa che stiamo lavorando con 8 bit . Quindi, ad esempio, possiamo scrivere il numero 2 come 0000 0010. Tuttavia, poiché si tratta del complemento a due, scriviamo un 2 negativo come questo: 1111 1110. Ciò che significa anche che la conversione in esadecimale è molto semplice. Cioè, devi semplicemente convertire ogni segmento a 4 bit direttamente in esadecimale. Nota che per dare un senso ai numeri negativi in questo schema dovrai prima capire il complemento a due. Se non capisci già il complemento a due, puoi leggere un'eccellente spiegazione, qui: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Una volta che un numero è nel complemento a due è assolutamente semplice convertirlo in esadecimale. In generale, la conversione da binario a esadecimale è molto semplice e, come vedrai nei prossimi due esempi, puoi passare direttamente dal complemento a due in esadecimale.
Esempio 1: convertire 2 in esadecimale.
1) Innanzitutto converti 2 in binario nel complemento a due:
2 (base 10) = 0000 0010 (base 2)
2) Ora converti binario in esadecimale:
0000 = 0x0 in hex
0010 = 0x2 in hex
therefore 2 = 0000 0010 = 0x02.
Esempio 2: Converti -2 (in complemento a due) in esadecimale.
1) Prima converti -2 in binario nel complemento a due:
-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) Ora converti in esadecimale:
1111 = 0xF in hex
1110 = 0xE in hex
therefore: -2 = 1111 1110 = 0xFE.
Ora che abbiamo trattato il concetto, scoprirai che possiamo ottenere ciò che vogliamo con un semplice mascheramento e spostamento. La cosa fondamentale da capire è che il byte che stai cercando di convertire è già nel complemento a due. Non fai questa conversione da solo. Penso che questo sia un grande punto di confusione su questo tema. Prendiamo ad esempio il seguente array di byte:
byte[] bytes = new byte[]{-2,2};
Li abbiamo appena convertiti manualmente in esadecimale, sopra, ma come possiamo farlo in Java? Ecco come:
Passaggio 1: creare uno StringBuffer per contenere il nostro calcolo.
StringBuffer buffer = new StringBuffer();
Passaggio 2: isolare i bit di ordine superiore, convertirli in esadecimali e aggiungerli al buffer
Dato il numero binario 1111 1110, possiamo isolare i bit di ordine superiore spostandoli prima di 4, quindi azzerando il resto del numero. Logicamente questo è semplice, tuttavia, i dettagli di implementazione in Java (e in molte lingue) introducono una ruga a causa dell'estensione del segno. In sostanza, quando si sposta un valore byte, Java prima converte il valore in un numero intero, quindi esegue l'estensione del segno. Quindi, mentre ti aspetteresti che 1111 1110 >> 4 sia 0000 1111, in realtà, in Java è rappresentato come il complemento a due 0xFFFFFFFF!
Quindi tornando al nostro esempio:
1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)
Possiamo quindi isolare i bit con una maschera:
1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex.
In Java possiamo fare tutto questo in un colpo solo:
Character.forDigit((bytes[0] >> 4) & 0xF, 16);
La funzione forDigit mappa semplicemente il numero che lo passi sull'insieme di numeri esadecimali 0-F.
Passaggio 3: Successivamente è necessario isolare i bit di ordine inferiore. Poiché i bit che vogliamo sono già nella posizione corretta, possiamo semplicemente mascherarli:
1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.
Come prima, in Java possiamo fare tutto questo in un colpo solo:
Character.forDigit((bytes[0] & 0xF), 16);
Mettendo tutto insieme possiamo farlo come un ciclo for e convertire l'intero array:
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));
}
Spero che questa spiegazione renda le cose più chiare per quelli di voi che si chiedono esattamente cosa sta succedendo nei molti esempi che troverete su Internet. Spero di non aver commesso errori eclatanti, ma suggerimenti e correzioni sono i benvenuti!
Character.digit()
, ad esempio(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
Il modo più veloce che ho ancora trovato per fare questo è il seguente:
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();
}
È ~ 50 volte più veloce di String.format
. se vuoi provarlo:
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
}
}
}
Modifica : ho appena trovato qualcosa di solo un po 'più veloce e che si mantiene su una riga ma non è compatibile con JRE 9. Utilizzare a proprio rischio
import javax.xml.bind.DatatypeConverter;
DatatypeConverter.printHexBinary(raw);
printHexBinary
da src.zip di jdk, che sembra 1 volta più veloce del primo metodo.
Prova in questo modo:
byte bv = 10;
String hexString = Integer.toHexString(bv);
Trattare con array (se ti ho capito bene):
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();
Come menzionato i poligenelubrificanti, String.format()
la risposta giusta è paragonabile a Integer.toHexString()
(poiché tratta i numeri negativi in modo corretto).
-1
.
bv
restituisce un singolo carattere esadecimale . Considerando che il resto del codice restituisce una stringa di caratteri esadecimali . Ho modificato il codice con il delimitatore in modo da poterlo capire ora.
Integer.toHexString
se si maschera il byte
con 0xFF
per annullare l'estensione del segno.
La migliore soluzione è questa tosta unita con un solo rivestimento:
String hex=DatatypeConverter.printHexBinary(byte[] b);
come menzionato qui
new BigInteger(byteArray).toString(16)
è la strada da percorrere allora. Sono problemi perf con quello ??
Se si desidera una rappresentazione esadecimale a larghezza costante, ovvero 0A
anziché A
, in modo da poter recuperare i byte in modo univoco, provare format()
:
StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
result.append(String.format("%02X", bb));
}
return result.toString();
Un modo breve e semplice per convertire byte[]
in stringa esadecimale utilizzando 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 classe di java.math.BigInteger
classe di sistema integrata ( java.math.BigInteger ) è compatibile con i dati binari ed esadecimali:
BigInteger(signum=1, byte[])
per creare un intero grande da byte[]
(impostare il suo primo parametro signum
= 1
per gestire correttamente i byte negativi)BigInteger.toString(16)
per convertire il numero intero grande in stringa esadecimalenew BigInteger("ffa74b", 16)
- non gestisce correttamente lo zero inizialeSe vuoi avere lo zero iniziale nel risultato esadecimale, controlla la sua dimensione e aggiungi lo zero mancante se necessario:
if (hex.length() % 2 == 1)
hex = "0" + hex;
Utilizzare new BigInteger(1, bytes)
, invece di new BigInteger(bytes)
, perché Java è " rotto in base alla progettazione " e il byte
tipo di dati non contiene byte ma numeri interi minuscoli firmati [-128 ... 127]. Se il primo byte è negativo, BigInteger
presuppone che si passi un intero grande negativo. Basta passare 1
come primo parametro ( signum=1
).
La conversione da hex a hexbyte[]
è complicata: a volte uno zero iniziale entra nell'output prodotto e dovrebbe essere pulito in questo modo:
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;
}
L'ultima nota è se se byte[]
ha diversi zero iniziali, andranno persi.
Se sei felice di usare una libreria esterna, la org.apache.commons.codec.binary.Hex
classe ha un encodeHex
metodo che accetta a byte[]
e restituisce a char[]
. Questo metodo è MOLTO più veloce dell'opzione di formattazione e incapsula i dettagli della conversione. Inoltre viene fornito con un decodeHex
metodo per la conversione opposta.
javax
spazio dei nomi non è sempre disponibile.
È possibile utilizzare il metodo dalla libreria del provider Bouncy Castle :
org.bouncycastle.util.encoders.Hex.toHexString(byteArray);
Il pacchetto Bouncy Castle Crypto è un'implementazione Java di algoritmi crittografici. Questo vaso contiene il provider JCE e l'API leggera per le API di crittografia Bouncy Castle per JDK da 1,5 a JDK 1,8.
Dipendenza da Maven:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.60</version>
</dependency>
o da Apache Commons Codec :
org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);
Il pacchetto Apache Commons Codec contiene un semplice codificatore e decodificatore per vari formati come Base64 e Hexadecimal. Oltre a questi codificatori e decodificatori ampiamente utilizzati, il pacchetto di codec mantiene anche una raccolta di utilità di codifica fonetica.
Dipendenza da Maven:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
Questo è il codice che ho trovato per eseguire il più veloce finora. L'ho eseguito su array di 109015 byte di lunghezza 32, in 23ms. Lo stavo eseguendo su una VM, quindi probabilmente funzionerà più velocemente su bare metal.
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;
}
Quindi puoi semplicemente farlo
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)
ritorna"-fdfcfbfb"
(int) 255
) poiché i byte Java sono firmati, quindi il risultato dovrebbe essere FF02030405
. Se provi la soluzione @Jerinaw sopra vedrai che stamperà l'output corretto. Vedi anche la soluzione di Svetlin Nakov di seguito.
Ecco una semplice funzione per convertire byte in esadecimali
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();
}
Altri hanno trattato il caso generale. Ma se hai una matrice di byte di una forma nota, ad esempio un indirizzo MAC, puoi:
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]);
Creare (e distruggere) un mucchio di String
istanze non è un buon modo se le prestazioni sono un problema.
Ignora quegli argomenti dettagliati (duplicati) che controllano le dichiarazioni if
. Questo è per (un altro) scopo educativo.
Progetto completo maven: http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/
Codifica ...
/**
* 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);
}
Decodifica ...
/**
* 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);
}
Questo è un modo molto veloce. Non sono necessarie librerie esterne.
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);
}
Non riuscivo a capire cosa intendevi esattamente con byte String, ma qui ci sono alcune conversioni da byte a String e viceversa, ovviamente c'è molto di più sulle documentazioni ufficiali
Integer intValue = 149;
Il valore byte corrispondente è:
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
recuperare il valore intero da una variabile Byte:
Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer
Da byte e numero intero a stringa esadecimale:
questo è il modo in cui lo faccio:
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
Conversione di una matrice di byte in una stringa esadecimale:
per quanto ne so non esiste una funzione semplice per convertire tutti gli elementi all'interno di una matrice di alcuni Object
in elementi di un'altra Object
, quindi devi farlo da solo. È possibile utilizzare le seguenti funzioni:
Da 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;
}
E da stringa esadecimale a 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;
}
È troppo tardi ma spero che questo possa aiutare alcuni altri;)
Ecco il tuo metodo veloce:
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];
}
Proprio come alcune altre risposte, consiglio di usare String.format()
e BigInteger
. Ma per interpretare l'array di byte come rappresentazione binaria big-endian anziché come rappresentazione binaria a complemento a due (con signum e uso incompleto della gamma di valori esadecimali) utilizzare BigInteger (int signum, byte [] magnitude) , non BigInteger (byte [] val ) .
Ad esempio, per una matrice di byte di lunghezza 8 utilizzare:
String.format("%016X", new BigInteger(1,bytes))
vantaggi:
Svantaggio:
Esempio:
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();
}
Esempio di output:
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