Wie initialisiere ich ein Byte-Array in Java?

138

Ich muss einige konstante Werte (UUIDs) in Byte-Array-Form in Java speichern und frage mich, wie diese statischen Arrays am besten initialisiert werden können. So mache ich es derzeit, aber ich denke, es muss einen besseren Weg geben.

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

Gibt es etwas, das ich verwenden könnte, das vielleicht weniger effizient ist, aber sauberer aussehen würde? beispielsweise:

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

Antworten:

111

Mit einer Funktion, die eine Hexa-Zeichenfolge in konvertiert byte[], können Sie dies tun

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

Ich würde vorschlagen, dass Sie die von Dave L in Konvertieren einer Zeichenfolgendarstellung eines Hex-Dumps in ein Byte-Array mit Java definierte Funktion verwenden.

Ich füge es hier für maximale Lesbarkeit ein:

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

Wenn Sie CDRIVES staticund zulassen final, ist der Leistungsabfall irrelevant.

Denys Séguret
quelle
78
byte[] myvar = "Any String you want".getBytes();

String-Literale können maskiert werden, um ein beliebiges Zeichen bereitzustellen:

byte[] CDRIVES = "\u00e0\u004f\u00d0\u0020\u00ea\u003a\u0069\u0010\u00a2\u00d8\u0008\u0000\u002b\u0030\u0030\u009d".getBytes();
petmez
quelle
50
Dreht das den String nicht "0000"auf {0x30,0x30,0x30,0x30}(ASCII) anstatt auf {0x00,0x00,0x00,0x00}(binär), wie vom Poster gewünscht?
JWW
5
Schauen Sie sich den Titel der Frage an. Dann schauen Sie zurück auf diese Antwort. Jetzt sag mir, was ist daran falsch? Es könnte das spezielle Problem des Posters nicht lösen, aber es hat mein Problem sicher gelöst. Ich musste einen String in ein Byte-Array umwandeln, um ihn als Startwert für einen Pseudozufallszahlengenerator zu verwenden, und das funktionierte wie ein Zauber.
e18r
@ e18r Es werden Bytes generiert, ja, aber Sie wissen nicht, welche, da dies vom Standardzeichensatz abhängt. Verwenden Sie mindestens .getBytes (gewünschte Codierung).
Quant
@petmez dumme Frage: in JAVA ist so etwas wie "" .getBytes (UTF_8)); (getBytes auf einer leeren Zeichenfolge) eine sichere Sache zu tun? ist es "legal"? Oder kann ich einfach machen: = neues Byte [0]; ?
Robert Achmann
1
@RobertAchmann "" .getbytes ("UTF-8") sollte ein leeres Array zurückgeben und ist vollkommen legal.
Jazzepi
33

In Java 6 gibt es eine Methode, die genau das tut, was Sie wollen:

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

Alternativ können Sie Google Guava verwenden :

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

Die Guava-Methode ist übertrieben, wenn Sie kleine Arrays verwenden. Guava hat aber auch Versionen, die Eingabestreams analysieren können. Dies ist eine nette Funktion, wenn es um große hexadezimale Eingaben geht.

stefan.schwetschke
quelle
Das Guava-Beispiel funktioniert nicht ganz wie geschrieben - es muss sein, base16().lowerCase().decode(...)wenn Sie Hex-Ziffern in Kleinbuchstaben haben. docs.guava-libraries.googlecode.com/git/javadoc/com/google/…
Peter DeGlopper
@PeterDeGlopper Gute Entdeckung, ich habe die Antwort aktualisiert, sodass der Code jetzt Zeichenfolgen mit Klein- und Großbuchstaben verarbeitet.
stefan.schwetschke
1
javax.xml.bindwurde leider in Java 9 entfernt.
randomdude999
7

Sie können die Java-UUID-Klasse verwenden, um diese Werte anstelle von Byte-Arrays zu speichern:

UUID

public UUID(long mostSigBits,
            long leastSigBits)

Erstellt eine neue UUID unter Verwendung der angegebenen Daten. mostSigBits wird für die höchstwertigen 64 Bit der UUID verwendet, und leastSigBits werden zu den niedrigstwertigen 64 Bit der UUID.

Jon
quelle
2

Für einen sauberen Prozess können Sie das ByteArrayOutputStream- Objekt verwenden ...

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

// schreibe alle Werte einzeln mit bObj

bObj.write(byte value)

// Wenn Sie fertig sind, können Sie das Byte [] mit abrufen

CDRIVES = bObj.toByteArray();

// als Sie den ähnlichen Vorgang auch für CMYDOCS und IEFRAME wiederholen können,

HINWEIS Dies ist keine effiziente Lösung, wenn Sie wirklich ein kleines Array haben.

Amit
quelle
2

Eine Lösung ohne Bibliotheken, zurückgegebene dynamische Länge, vorzeichenlose Ganzzahlinterpretation (kein Zweierkomplement)

    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 };
    }
}
ZMitton
quelle
1

Unter diesen Umständen ist es meine bevorzugte Option, org.apache.commons.codec.binary.Hexnützliche APIs für die Konvertierung zwischen Stringy hex und binär zu verwenden. Beispielsweise:

  1. Hex.decodeHex(char[] data)Dies wirft ein, DecoderExceptionwenn das Array nicht hexadezimale Zeichen enthält oder wenn eine ungerade Anzahl von Zeichen vorhanden ist.

  2. Hex.encodeHex(byte[] data)ist das Gegenstück zur obigen Decodierungsmethode und spuckt die aus char[].

  3. Hex.encodeHexString(byte[] data)die von einem byteArray zurück in ein konvertiert String.

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

rbrtl
quelle
1

Sie können diese Dienstprogrammfunktion verwenden:

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

Im Gegensatz zu Varianten von Denys Séguret und stefan.schwetschke können Trennzeichen (Leerzeichen, Tabulatoren usw.) in die Eingabezeichenfolge eingefügt werden, um die Lesbarkeit zu verbessern.

Anwendungsbeispiel:

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");
John McClane
quelle
1

Der kleinste interne Typ, der zur Kompilierungszeit durch Hex-Zahlen zugewiesen werden kann, ist char , as

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

Um ein äquivalentes Byte-Array zu haben, kann man Konvertierungen als bereitstellen

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;
}
Sam Ginrich
quelle
-2
private static final int[] CDRIVES = new int[] {0xe0, 0xf4, ...};

und nach dem Zugriff in Byte konvertieren.

Frankie
quelle