423 votes

Convertir la représentation en chaîne d'un vidage hexagonal en un tableau d'octets en utilisant Java ?

Je cherche un moyen de convertir une longue chaîne (à partir d'un vidage), qui représente des valeurs hexagonales dans un tableau d'octets.

Je n'aurais pas pu le formuler mieux que la personne qui a posté le message. la même question ici .

Mais pour rester original, je vais le formuler à ma façon : supposons que j'ai une chaîne de caractères "00A0BF" que je voudrais voir interprété comme le

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

que dois-je faire ?

Je suis un novice de Java et j'ai fini par utiliser BigInteger et en faisant attention aux zéros hexagonaux de tête. Mais je pense que c'est moche et je suis sûr que je rate quelque chose de simple.

0 votes

0 votes

J'ai apprivoisé BigInteger aquí .

0 votes

FWIW String.getBytes() ne fonctionnera pas comme vous le pensez. J'ai dû l'apprendre à la dure. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }

706voto

Dave L. Points 19623

Mise à jour (2021) - Java 17 comprend désormais java.util.HexFormat (cela n'a pris que 25 ans) :

HexFormat.of().parseHex(s)


Pour les anciennes versions de Java :

Voici une solution qui, à mon avis, est meilleure que toutes celles qui ont été publiées jusqu'à présent :

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

Raisons pour lesquelles il s'agit d'une amélioration :

  • Sûr avec des zéros en tête (contrairement à BigInteger) et avec des valeurs d'octets négatives (contrairement à Byte.parseByte)

  • Ne convertit pas la chaîne en un char[] ou créer des objets StringBuilder et String pour chaque octet.

  • Pas de dépendances de bibliothèque qui pourraient ne pas être disponibles

N'hésitez pas à ajouter la vérification des arguments via assert ou des exceptions si l'argument n'est pas connu pour être sûr.

0 votes

Merci. Il devrait y avoir un intégré pour cela. Surtout que Byte.parseByte croque sur les valeurs négatives est encombrant.

0 votes

Produit un résultat erroné. Voir l'implémentation apache dans le post ci-dessous.

3 votes

Pouvez-vous donner un exemple de décodage incorrect, ou expliquer en quoi il l'est ?

345voto

FractalizeR Points 12887

Des phrases toutes faites :

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

Avertissements :

  • Dans Java 9 Jigsaw, cela ne fait plus partie de l'ensemble (par défaut) java.se Root de sorte qu'il en résultera une ClassNotFoundException à moins que vous ne spécifiiez --add-modules java.se.ee (merci à @ eckes )
  • Non disponible sur Android (grâce à Fabian pour avoir noté cela), mais vous pouvez simplement prendre le code source si votre système ne dispose pas de javax.xml pour une raison quelconque. Merci à @ Bert Regelink pour l'extraction de la source.

18 votes

À mon avis, cette réponse devrait être la réponse acceptée/supplémentaire car elle est courte et propre (contrairement à la réponse de @DaveL) et ne nécessite aucune librairie externe (comme la réponse de skaffman). Aussi, <Enter une blague usée sur la réinvention du vélo> .

11 votes

La classe datatypeconverter n'est pas disponible dans Android par exemple.

4 votes

Avertissement : dans Java 9 Jigsaw, cela ne fait plus partie de l'option (par défaut) java.se La racine est réglée de manière à ce qu'il en résulte un ClassNotFoundException à moins que vous ne spécifiez --add-modules java.se.ee

101voto

skaffman Points 197885

La classe Hex dans commons-codec devrait le faire pour vous.

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

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

7 votes

Cela semble également bon. Voir org.apache.commons.codec.binary.Hex.decodeHex()

0 votes

C'était intéressant. Mais j'ai trouvé leur solution difficile à suivre. A-t-elle des avantages par rapport à ce que vous avez proposé (à part la vérification du nombre pair de caractères) ?

44voto

jontro Points 3423

Vous pouvez maintenant utiliser Codage de base en guava pour y parvenir.

BaseEncoding.base16().decode(string);

Pour l'inverser, utilisez

BaseEncoding.base16().encode(bytes);

24voto

GrkEngineer Points 1253

Le site HexBinaryAdapter offre la possibilité d'effectuer des opérations de marshal et de démarshal entre String y byte[] .

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

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

C'est juste un exemple que j'ai tapé... En fait, je l'utilise tel quel et je n'ai pas besoin de créer une méthode distincte pour l'utiliser.

6 votes

Il ne fonctionne que si la chaîne d'entrée (hexString) a un nombre pair de caractères. Sinon : Exception dans le thread "main" java.lang.IllegalArgumentException : hexBinary needs to be even-length :

4 votes

Oh, merci de me le faire remarquer. Un utilisateur ne devrait pas avoir un nombre impair de caractères car le tableau d'octets est représenté par {0x00,0xA0,0xBf}. Chaque octet comporte deux chiffres hexadécimaux ou nibbles. Donc n'importe quel nombre d'octets devrait toujours avoir un nombre pair de caractères. Merci de l'avoir mentionné.

8 votes

Vous pouvez utiliser java.xml.bind.DatatypeConverter.parseHexBinary(hexString) directement au lieu d'utiliser HexBinaryAdapter (qui appelle à son tour DatatypeConverter). De cette façon, vous n'avez pas besoin de créer un objet d'instance d'adaptateur (puisque les méthodes de DatatypeConverter sont statiques).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X