Come posso inizializzare un array di byte in Java?


138

Devo memorizzare alcuni valori costanti (UUID) in forma di array di byte in Java e mi chiedo quale sarebbe il modo migliore per inizializzare tali array statici. Questo è come lo sto attualmente facendo, ma sento che ci deve essere un modo migliore.

private static final byte[] CDRIVES = new byte[] { (byte)0xe0, 0x4f, (byte)0xd0,
    0x20, (byte)0xea, 0x3a, 0x69, 0x10, (byte)0xa2, (byte)0xd8, 0x08, 0x00, 0x2b,
    0x30, 0x30, (byte)0x9d };
private static final byte[] CMYDOCS = new byte[] { (byte)0xba, (byte)0x8a, 0x0d,
    0x45, 0x25, (byte)0xad, (byte)0xd0, 0x11, (byte)0x98, (byte)0xa8, 0x08, 0x00,
    0x36, 0x1b, 0x11, 0x03 };
private static final byte[] IEFRAME = new byte[] { (byte)0x80, 0x53, 0x1c,
    (byte)0x87, (byte)0xa0, 0x42, 0x69, 0x10, (byte)0xa2, (byte)0xea, 0x08,
    0x00, 0x2b, 0x30, 0x30, (byte)0x9d };
...
and so on

C'è qualcosa che potrei usare che potrebbe essere meno efficiente, ma apparirebbe più pulito? per esempio:

private static final byte[] CDRIVES =
    new byte[] { "0xe04fd020ea3a6910a2d808002b30309d" };

Risposte:


111

Utilizzando una funzione che converte una stringa hexa in byte[], si potrebbe fare

byte[] CDRIVES = hexStringToByteArray("e04fd020ea3a6910a2d808002b30309d");

Suggerirei di utilizzare la funzione definita da Dave L in Converti una rappresentazione in formato stringa di un dump esadecimale in una matrice di byte usando Java?

Lo inserisco qui per la massima leggibilità:

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;
}

Se si lasciano CDRIVES statice final, il calo delle prestazioni è irrilevante.


78
byte[] myvar = "Any String you want".getBytes();

I letterali di stringa possono essere sfuggiti per fornire qualsiasi carattere:

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();

50
Questo non trasforma la stringa "0000"in {0x30,0x30,0x30,0x30}(ASCII) piuttosto che {0x00,0x00,0x00,0x00}(binario) come desiderato dal poster?
JWW

5
Guarda il titolo della domanda. Quindi guarda indietro a questa risposta. Ora dimmi, cosa c'è che non va? Potrebbe non risolvere il particolare problema del poster, ma ha sicuramente risolto il mio. Avevo bisogno di trasformare una stringa in un array di byte da utilizzare come seme per un generatore di numeri pseudocasuali e questo ha funzionato come un incantesimo.
e18r

@ e18r Sta generando byte, sì, ma non si sa quale sia questa dipendenza dal set di caratteri predefinito. Almeno usa .getBytes (desiderataEncoding).
quant

@petmez domanda stupida: in JAVA, c'è qualcosa come "" .getBytes (UTF_8)); (getBytes su una stringa vuota) una cosa sicura da fare? è "legale"? O posso semplicemente fare: = new byte [0]; ?
Robert Achmann

1
@RobertAchmann "" .getbytes ("UTF-8") dovrebbe restituire un array vuoto ed è perfettamente legale.
Jazzepi,

33

In Java 6, esiste un metodo che fa esattamente quello che vuoi:

private static final byte[] CDRIVES = javax.xml.bind.DatatypeConverter.parseHexBinary("e04fd020ea3a6910a2d808002b30309d")

In alternativa, puoi utilizzare Google Guava :

import com.google.common.io.BaseEncoding;
private static final byte[] CDRIVES = BaseEncoding.base16().lowerCase().decode("E04FD020ea3a6910a2d808002b30309d".toLowerCase());

Il metodo Guava è eccessivo, quando si utilizzano array di piccole dimensioni. Ma Guava ha anche versioni che possono analizzare i flussi di input. Questa è una bella caratteristica quando si hanno a che fare con grandi input esadecimali.


L'esempio di Guava non funziona esattamente come scritto - deve essere base16().lowerCase().decode(...)se hai cifre esadecimali minuscole. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…
Peter DeGlopper

@PeterDeGlopper Buona scoperta, ho aggiornato la risposta in modo che il codice ora gestisca le stringhe con caratteri sia maiuscoli che maiuscoli.
stefan.schwetschke,

1
javax.xml.bindè stato purtroppo rimosso in Java 9.
randomdude999

7

È possibile utilizzare la classe UUID Java per archiviare questi valori, anziché array di byte:

UUID

public UUID(long mostSigBits,
            long leastSigBits)

Crea un nuovo UUID utilizzando i dati specificati. mostSigBits viene utilizzato per i 64 bit più significativi dell'UUID e leastSigBits diventa i 64 bit meno significativi dell'UUID.


2

Per quanto riguarda un processo pulito, puoi usare l' oggetto ByteArrayOutputStream ...

ByteArrayOutputStream bObj = new ByteArrayOutputStream();
bObj.reset();

// scrive tutti i valori su bObj uno per uno usando

bObj.write(byte value)

// una volta terminato, puoi ottenere il byte [] usando

CDRIVES = bObj.toByteArray();

// di quanto puoi ripetere il processo simile anche per CMYDOCS e IEFRAME,

NOTA Questa non è una soluzione efficiente se si dispone davvero di un array piccolo.


2

Una soluzione senza librerie, lunghezza dinamica restituita, interpretazione intera senza segno (non complemento a due)

    public static byte[] numToBytes(int num){
    if(num == 0){
        return new byte[]{};
    }else if(num < 256){
        return new byte[]{ (byte)(num) };
    }else if(num < 65536){
        return new byte[]{ (byte)(num >>> 8),(byte)num };
    }else if(num < 16777216){
        return new byte[]{ (byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }else{ // up to 2,147,483,647
        return new byte[]{ (byte)(num >>> 24),(byte)(num >>> 16),(byte)(num >>> 8),(byte)num };
    }
}

1

La mia opzione preferita in questa circostanza è quella di utilizzare le org.apache.commons.codec.binary.HexAPI utili per la conversione tra Stringy esadecimale e binario. Per esempio:

  1. Hex.decodeHex(char[] data)che genera un DecoderExceptionse ci sono caratteri non esadecimali nella matrice o se c'è un numero dispari di caratteri.

  2. Hex.encodeHex(byte[] data)è la controparte del metodo di decodifica sopra riportato e sputa il char[].

  3. Hex.encodeHexString(byte[] data)che converte da un bytearray in a String.

Uso: Hex.decodeHex("dd645a2564cbe648c8336d2be5eafaa6".toCharArray())


1

È possibile utilizzare questa funzione di utilità:

public static byte[] fromHexString(String src) {
    byte[] biBytes = new BigInteger("10" + src.replaceAll("\\s", ""), 16).toByteArray();
    return Arrays.copyOfRange(biBytes, 1, biBytes.length);
}

A differenza delle varianti di Denys Séguret e stefan.schwetschke, consente di inserire simboli di separazione (spazi, tabulazioni, ecc.) Nella stringa di input, rendendola più leggibile.

Esempio di utilizzo:

private static final byte[] CDRIVES
    = fromHexString("e0 4f d0 20 ea 3a 69 10 a2 d8 08 00 2b 30 30 9d");
private static final byte[] CMYDOCS
    = fromHexString("BA8A0D4525ADD01198A80800361B1103");
private static final byte[] IEFRAME
    = fromHexString("80531c87 a0426910 a2ea0800 2b30309d");

1

Il tipo interno più piccolo, che al momento della compilazione può essere assegnato da numeri esadecimali è char , come

private static final char[] CDRIVES_char = new char[] {0xe0, 0xf4, ...};

Per avere un array di byte equivalente è possibile distribuire conversioni come

public static byte[] charToByteArray(char[] x)
{
    final byte[] res = new byte[x.length];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = (byte) x[i];
    }
    return res;
}

public static byte[][] charToByteArray(char[][] x)
{
    final byte[][] res = new byte[x.length][];
    for (int i = 0; i < x.length; i++)
    {
        res[i] = charToByteArray(x[i]);
    }
    return res;
}

-2
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

e dopo l'accesso convertire in byte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.