Konvertieren Sie eine Zeichenfolgendarstellung eines Hex-Dumps mit Java in ein Byte-Array?

Lesezeit: 9 Minuten

Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
rafraf

Ich suche nach einer Möglichkeit, eine lange Zeichenfolge (aus einem Dump) zu konvertieren, die Hex-Werte in ein Byte-Array darstellt.

Ich hätte es nicht besser formulieren können als die Person, die gepostet hat hier die gleiche Frage.

Aber um es originell zu halten, formuliere ich es auf meine eigene Weise: Angenommen, ich habe eine Zeichenfolge "00A0BF" das möchte ich so interpretieren

byte[] {0x00,0xA0,0xBf}

was soll ich machen?

Ich bin ein Java-Anfänger und habe es schließlich verwendet BigInteger und achten Sie auf führende Hex-Nullen. Aber ich finde es hässlich und ich bin sicher, dass ich etwas Einfaches vermisse.

  • Siehe auch stackoverflow.com/questions/9655181/….

    – flow2k

    23. Oktober 2018 um 18:54 Uhr

  • Ich habe gezähmt BigInteger Hier.

    – John McClane

    25. November 2018 um 1:34 Uhr

  • FWIW String.getBytes() wird nicht so funktionieren, wie du denkst. Musste das auf die harte Tour lernen. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }

    – tir38

    11. September 2019 um 17:05 Uhr

Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
David L.

Aktualisierung (2021) – Java 17 jetzt beinhaltet java.util.HexFormat (dauerte nur 25 Jahre):

HexFormat.of().parseHex(s)


Für ältere Java-Versionen:

Hier ist eine Lösung, die meiner Meinung nach besser ist als alle bisher geposteten:

/* s must be an even-length string. */
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;
}

Gründe für eine Verbesserung:

  • Sicher mit führenden Nullen (im Gegensatz zu BigInteger) und mit negativen Bytewerten (im Gegensatz zu Byte.parseByte)

  • Konvertiert den String nicht in a char[]oder erstellen Sie StringBuilder- und String-Objekte für jedes einzelne Byte.

  • Keine Bibliotheksabhängigkeiten, die möglicherweise nicht verfügbar sind

Fühlen Sie sich frei, die Argumentprüfung über hinzuzufügen assert oder Ausnahmen, wenn das Argument nicht als sicher bekannt ist.

  • Können Sie ein Beispiel geben, das falsch dekodiert wurde, oder erklären, warum es falsch ist?

    – David L.

    17. April 2011 um 14:35 Uhr


  • Es funktioniert nicht für den String “0”. Es löst eine java.lang.StringIndexOutOfBoundsException aus

    – ovdsrn

    8. Juni 2011 um 20:06 Uhr

  • “0” ist keine gültige Eingabe. Bytes erfordern jeweils zwei Hexadezimalziffern. In der Antwort heißt es: „Sie können gerne eine Argumentüberprüfung hinzufügen … wenn das Argument nicht als sicher bekannt ist.“

    – David L.

    9. Juni 2011 um 16:42 Uhr

  • javax.xml.bind.DatatypeConverter.parseHexBinary(hexString) scheint in meinen Mikrotests etwa 20% schneller zu sein als die obige Lösung (für was auch immer sie wert sind) und löst korrekt Ausnahmen bei ungültigen Eingaben aus (z. B. “gg” ist kein gültiger hexString, gibt aber -77 zurück, wenn die vorgeschlagene Lösung verwendet wird).

    – Trevor Freemann

    4. April 2012 um 18:31 Uhr

  • @DaedalusAlpha Es hängt von Ihrem Kontext ab, aber normalerweise finde ich es besser, mit solchen Dingen schnell und laut zu scheitern, damit Sie Ihre Annahmen korrigieren können, anstatt stillschweigend falsche Daten zurückzugeben.

    – David L.

    17. Juni 2015 um 16:03 Uhr

1646750833 0 Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
Wladislav Rastrusny

Einzeiler:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Warnungen:

  • in Java 9 Jigsaw ist dies nicht mehr Teil des (Standard-) java.se-Stammsatzes, sodass es zu einer ClassNotFoundException führt, es sei denn, Sie geben –add-modules java.se.ee an (danke an @eckes)
  • Nicht verfügbar für Android (danke an Fabian für die Notiz), aber Sie können einfach den Quellcode nehmen, wenn Ihr System fehlt javax.xml aus irgendeinem Grund. Dank an @Bert Regelink um die Quelle zu extrahieren.

  • IMHO sollte dies die akzeptierte / beste Antwort sein, da es kurz ist und reinigen (im Gegensatz zur Antwort von @ DaveL) und erfordert keine externen Bibliotheken (wie die Antwort von skaffman). Ebenfalls, .

    – Priidu Neemre

    18. August 2015 um 12:40 Uhr


  • die datatypeconverter-Klasse ist beispielsweise in Android nicht verfügbar.

    – Fabian

    10. Februar 2016 um 12:41 Uhr

  • Warnung: in Java 9 Jigsaw ist dies nicht mehr Teil des (Standard) java.se Wurzelsatz, so dass es zu a führt ClassNotFoundException es sei denn, Sie geben an --add-modules java.se.ee

    – eckes

    10. November 2016 um 12:17 Uhr

  • @dantebarba denke ich javax.xml.bind.DatatypeConverter bietet bereits eine Methode zum Codieren/Decodieren von Base64-Daten. Sehen parseBase64Binary() und printBase64Binary().

    – DragShot

    3. Juli 2017 um 22:18 Uhr

  • Um die Probleme mit zu ergänzen DataTypeConverter, Java SE 11 hat die JAXB-API vollständig entfernt und ist jetzt nur noch in Java EE enthalten. Sie können es auch als Maven-Abhängigkeit hinzufügen, wie hier vorgeschlagen: stackoverflow.com/a/43574427/7347751

    – David Mordigal

    30. Januar 2019 um 5:51 Uhr

1646750834 660 Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
Skaffmann

Die Hex-Klasse im Commons-Codec sollte das für Sie erledigen.

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

  • Das sieht auch gut aus. Siehe org.apache.commons.codec.binary.Hex.decodeHex()

    – David L.

    26. September 2008 um 17:46 Uhr

  • Es war interessant. Aber ich fand ihre Lösung schwer nachzuvollziehen. Hat es Vorteile gegenüber dem, was Sie vorgeschlagen haben (außer der Überprüfung auf eine gerade Anzahl von Zeichen)?

    – raffaf

    27. September 2008 um 1:06 Uhr

1646750835 88 Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
Jontro

Sie können jetzt verwenden BaseEncoding in guava um das zu erreichen.

BaseEncoding.base16().decode(string);

Um es umzukehren, verwenden Sie

BaseEncoding.base16().encode(bytes);

Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
David L.

Eigentlich finde ich die BigInteger-Lösung sehr schön:

new BigInteger("00A0BF", 16).toByteArray();

Bearbeiten: Nicht sicher für führende Nullenwie auf dem Plakat vermerkt.

  • Dachte ich anfangs auch. Und danke, dass Sie es dokumentiert haben – ich dachte nur, ich sollte es tun … es hat einige seltsame Dinge getan, die ich nicht wirklich verstanden habe – wie einige führende 0x00 wegzulassen und auch die Reihenfolge von 1 Byte in einer 156-Byte-Zeichenfolge zu verwechseln I spielte mit.

    – raffaf

    26. September 2008 um 16:43 Uhr

  • Das ist ein guter Punkt über führende Nullen. Ich bin mir nicht sicher, ob ich glaube, dass es die Reihenfolge der Bytes verwechseln könnte, und wäre sehr daran interessiert, es demonstriert zu sehen.

    – David L.

    26. September 2008 um 16:55 Uhr

  • Ja, sobald ich es gesagt habe, habe ich es mir auch nicht geglaubt 🙂 Ich habe einen Vergleich des Byte-Arrays von BigInteger mit mmyers’fromHexString und (ohne 0x00) mit dem anstößigen String durchgeführt – sie waren identisch. Die “Verwechslung” ist passiert, aber es kann etwas anderes gewesen sein. Ich werde morgen genauer hinschauen

    – raffaf

    26. September 2008 um 17:09 Uhr

  • Das Problem mit BigInteger ist, dass es ein “Vorzeichenbit” geben muss. Wenn das führende Byte das High-Bit gesetzt hat, hat das resultierende Byte-Array eine zusätzliche 0 an der 1. Position. Aber immer noch +1.

    – Grau

    28. Oktober 2011 um 16:20 Uhr

1646750836 552 Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
Gemeinschaft

Einzeiler:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Für diejenigen unter Ihnen, die sich für den eigentlichen Code dahinter interessieren Einzeiler von FractalizeR (ich brauchte das, da javax.xml.bind nicht für Android verfügbar ist (standardmäßig)), das kommt von com.sun.xml.internal.bind.DatatypeConverterImpl.java :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( 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 char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}

  • Dachte ich anfangs auch. Und danke, dass Sie es dokumentiert haben – ich dachte nur, ich sollte es tun … es hat einige seltsame Dinge getan, die ich nicht wirklich verstanden habe – wie einige führende 0x00 wegzulassen und auch die Reihenfolge von 1 Byte in einer 156-Byte-Zeichenfolge zu verwechseln I spielte mit.

    – raffaf

    26. September 2008 um 16:43 Uhr

  • Das ist ein guter Punkt über führende Nullen. Ich bin mir nicht sicher, ob ich glaube, dass es die Reihenfolge der Bytes verwechseln könnte, und wäre sehr daran interessiert, es demonstriert zu sehen.

    – David L.

    26. September 2008 um 16:55 Uhr

  • Ja, sobald ich es gesagt habe, habe ich es mir auch nicht geglaubt 🙂 Ich habe einen Vergleich des Byte-Arrays von BigInteger mit mmyers’fromHexString und (ohne 0x00) mit dem anstößigen String durchgeführt – sie waren identisch. Die “Verwechslung” ist passiert, aber es kann etwas anderes gewesen sein. Ich werde morgen genauer hinschauen

    – raffaf

    26. September 2008 um 17:09 Uhr

  • Das Problem mit BigInteger ist, dass es ein “Vorzeichenbit” geben muss. Wenn das führende Byte das High-Bit gesetzt hat, hat das resultierende Byte-Array eine zusätzliche 0 an der 1. Position. Aber immer noch +1.

    – Grau

    28. Oktober 2011 um 16:20 Uhr

Konvertieren Sie eine Zeichenfolgendarstellung eines Hex Dumps mit Java in ein
Anil Bharadia

Die HexBinaryAdapter bietet die Möglichkeit zum Marshallen und Unmarshall zwischen String und byte[].

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

Das ist nur ein Beispiel, das ich eingegeben habe … Ich verwende es eigentlich nur so, wie es ist, und muss keine separate Methode für die Verwendung erstellen.

  • Es funktioniert nur, wenn die Eingabezeichenfolge (hexString) eine gerade Anzahl von Zeichen hat. Sonst: Ausnahme im Thread “main” java.lang.IllegalArgumentException: hexBinary muss gerade Länge haben:

    – ovdsrn

    8. Juni 2011 um 20:15 Uhr


  • Oh, danke für den Hinweis. Ein Benutzer sollte wirklich keine ungerade Anzahl von Zeichen haben, da das Byte-Array als {0x00,0xA0,0xBf} dargestellt wird. Jedes Byte hat zwei Hexadezimalziffern oder Halbbytes. Eine beliebige Anzahl von Bytes sollte also immer eine gerade Anzahl von Zeichen haben. Danke, dass du das erwähnt hast.

    – GrkIngenieur

    16. Juni 2011 um 15:54 Uhr

  • Sie können java.xml.bind.DatatypeConverter.parseHexBinary(hexString) direkt verwenden, anstatt HexBinaryAdapter zu verwenden (der wiederum DatatypeConverter aufruft). Auf diese Weise müssen Sie kein Adapterinstanzobjekt erstellen (da DatatypeConverter-Methoden statisch sind).

    – Trevor Freemann

    4. April 2012 um 18:33 Uhr

  • javax.xml.bind.* ist in Java 9 nicht mehr verfügbar. Das Gefährliche ist, dass Code, der es verwendet, unter Java 1.8 oder früher (Java 9 mit Quelleinstellungen früher) kompiliert wird, aber eine Laufzeitausnahme erhält, die unter Java 9 ausgeführt wird.

    – Stephen M -im Streik-

    28. August 2017 um 16:52 Uhr

975640cookie-checkKonvertieren Sie eine Zeichenfolgendarstellung eines Hex-Dumps mit Java in ein Byte-Array?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy