171 Stimmen

Wie konvertiere ich in Java ein Byte-Array in eine Zeichenkette aus Hex-Ziffern, wobei führende Nullen erhalten bleiben?

Ich arbeite mit einigen Beispiel-Java-Code für die Herstellung von md5 Hashes. Ein Teil wandelt die Ergebnisse von Bytes in eine Zeichenkette aus Hex-Ziffern um:

byte messageDigest[] = algorithm.digest();     
StringBuffer hexString = new StringBuffer();
for (int i=0;i<messageDigest.length;i++) {
    hexString.append(Integer.toHexString(0xFF & messageDigest[i]));
    }

Es funktioniert jedoch nicht ganz, da toHexString offenbar führende Nullen abschneidet. Also, was ist der einfachste Weg, um von Byte-Array zu Hex-String, die die führenden Nullen behält gehen?

142voto

Brandon DuRette Punkte 4730

Überprüfen Sie Hex.encodeHexString von Apache Commons Codec .

import org.apache.commons.codec.binary.Hex;

String hex = Hex.encodeHexString(bytes);

14 Stimmen

Und wenn Sie md5 mit Apache Commons Codec machen, schauen Sie sich DigestUtils.md5Hex()

1 Stimmen

DigestUtils macht die Dinge ein wenig einfacher, aber es kann mühsam sein, es in Ihr Projekt einzubinden. Ich persönlich stöhne bei dem Gedanken, mich mit pom-Dateien herumzuschlagen.

123voto

Ayman Punkte 10755

Sie können die unten stehende verwenden. Ich habe dies mit führenden Null-Bytes und auch mit anfänglichen negativen Bytes getestet

public static String toHex(byte[] bytes) {
    BigInteger bi = new BigInteger(1, bytes);
    return String.format("%0" + (bytes.length << 1) + "X", bi);
}

Wenn Sie Hexadezimalziffern in Kleinbuchstaben wünschen, verwenden Sie "x" im Format String.

3 Stimmen

Keine externen Abhängigkeiten, schön und kurz. Und wenn Sie wissen, dass Sie 16 Bytes / 32 Hexadezimalziffern haben, lässt sich Ihre Lösung auf einen einfachen Einzeiler reduzieren. Cool!

0 Stimmen

Funktioniert prima, danke.

0 Stimmen

Ich danke Ihnen. Ich brauchte dies, um ein 16-Byte-IPv6-Byte-Array in eine Null-gefüllte Hex-String in Scala zu konvertieren: f"${BigInt(1, myIpv6ByteArray)}%032x" .

115voto

Michael Myers Punkte 183216

Ein einfacher Ansatz wäre es, zu prüfen, wie viele Ziffern ausgegeben werden durch Integer.toHexString() und fügen Sie bei Bedarf jedem Byte eine führende Null hinzu. Etwa so:

public static String toHexString(byte[] bytes) {
    StringBuilder hexString = new StringBuilder();

    for (int i = 0; i < bytes.length; i++) {
        String hex = Integer.toHexString(0xFF & bytes[i]);
        if (hex.length() == 1) {
            hexString.append('0');
        }
        hexString.append(hex);
    }

    return hexString.toString();
}

0 Stimmen

Würde es nicht "10" für Byte 0x01 ergeben?

4 Stimmen

Nein, die 0 wird angehängt an hexString bevor der Hex-Wert dies tut.

0 Stimmen

Als ich anrief Integer.toHexString((byte)0xff) wird wegen der Vorzeichenerweiterung "ffffffff" zurückgegeben. Man muss also möglicherweise die letzten beiden Zeichen der zurückgegebenen Zeichenfolge nehmen.

40voto

Gareth Punkte 401

Die Methode javax.xml.bind.DatatypeConverter.printHexBinary() , Teil des Java-Architektur für XML-Bindung (JAXB) war eine bequeme Möglichkeit zur Umwandlung einer byte[] in eine Hex-Zeichenkette. Die DatatypeConverter Klasse enthielt auch viele andere nützliche Methoden zur Datenmanipulation.

In Java 8 und früher war JAXB Teil der Java-Standardbibliothek. Sie war Abgelehnt mit Java 9 und entfernt mit Java 11 als Teil der Bemühungen, alle Java EE-Pakete in ihre eigenen Bibliotheken zu verschieben. Das ist eine lange Geschichte . Jetzt, javax.xml.bind gibt es nicht, und wenn Sie JAXB verwenden wollen, das die DatatypeConverter installieren, müssen Sie die JAXB-API y JAXB-Laufzeit von Maven.

Beispiel für die Verwendung:

byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);

Wird dazu führen:

000086003D

0 Stimmen

Für den Rückwärtsgang gibt es DatatypeConverter.parseHexBinary(hexString) auch.

2 Stimmen

Bitte beachten Sie, dass ab Java 11, java.xml Paket ist nicht mehr Teil des JDK.

35voto

Jemenake Punkte 1842

Steves Beiträge haben mir gut gefallen, aber er hätte auf einige Variablen verzichten und dadurch einige Zeilen einsparen können.

public static String toHexString(byte[] bytes) {
    char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for ( int j = 0; j < bytes.length; j++ ) {
        v = bytes[j] & 0xFF;
        hexChars[j*2] = hexArray[v/16];
        hexChars[j*2 + 1] = hexArray[v%16];
    }
    return new String(hexChars);
}

Was mir daran gefällt, ist, dass es einfach ist, genau zu sehen, was es tut (anstatt sich auf eine magische BigInteger-Blackbox-Konvertierung zu verlassen), und man muss sich auch keine Gedanken über Eckfälle wie führende Nullen und so machen. Diese Routine nimmt jedes 4-Bit-Nibble und wandelt es in ein Hex-Char um. Und sie benutzt einen Tabellen-Lookup, also ist sie wahrscheinlich schnell. Es könnte wahrscheinlich noch schneller gehen, wenn man v/16 und v%16 durch bitweise Verschiebungen und AND's ersetzt, aber ich bin zu faul, das jetzt zu testen.

0 Stimmen

Toll! Verbessert den "append is slow"-Gedanken von Steve, indem es für ein Byte-Array beliebiger Größe funktioniert.

0 Stimmen

Ändern Sie v/16 in v >>> 4 und v%16 in v & 0x0F, um die Geschwindigkeit zu erhöhen. Sie können auch j << 1 verwenden, um mit 2 zu multiplizieren (obwohl der Compiler dies wahrscheinlich für Sie tut).

0 Stimmen

Oder, noch besser, addieren Sie den Wert zu '0', um das Zeichen zu erhalten, so dass keine Nachschlagetabelle erforderlich ist. z. B. hexChars[j << 1] = (byte)(v >>> 4 + '0')

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X