J'ai un tableau d'octets. Je veux que chaque chaîne d'octets de ce tableau soit convertie en sa valeur hexadécimale correspondante.
Existe-t-il une fonction en Java pour convertir un tableau d'octets en hexadécimal ?
J'ai un tableau d'octets. Je veux que chaque chaîne d'octets de ce tableau soit convertie en sa valeur hexadécimale correspondante.
Existe-t-il une fonction en Java pour convertir un tableau d'octets en hexadécimal ?
byte[] bytes = {-1, 0, 1, 2, 3 };
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X ", b));
}
System.out.println(sb.toString());
// prints "FF 00 01 02 03 "
java.util.Formatter
syntaxe
%[flags][width]conversion
'0'
- Le résultat sera mis à zéro2
'X'
- Le résultat est formaté sous la forme d'un nombre entier hexadécimal, en majuscules.En regardant le texte de la question, il est également possible que ce soit ce qui est demandé :
String[] arr = {"-1", "0", "10", "20" };
for (int i = 0; i < arr.length; i++) {
arr[i] = String.format("%02x", Byte.parseByte(arr[i]));
}
System.out.println(java.util.Arrays.toString(arr));
// prints "[ff, 00, 0a, 14]"
Plusieurs réponses ici utilise Integer.toHexString(int)
C'est faisable, mais avec quelques réserves. Puisque le paramètre est un int
une conversion primitive d'élargissement est effectuée sur la base de l'adresse de l'utilisateur. byte
argument, qui implique l'extension du signe.
byte b = -1;
System.out.println(Integer.toHexString(b));
// prints "ffffffff"
Le système 8-bit byte
qui est signé en Java, est prolongé par un signe en 32 bits. int
. Pour défaire efficacement cette extension de signe, on peut masquer le byte
con 0xFF
.
byte b = -1;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "ff"
Un autre problème lié à l'utilisation de toHexString
c'est qu'il ne contient pas de zéros :
byte b = 10;
System.out.println(Integer.toHexString(b & 0xFF));
// prints "a"
Ces deux facteurs combinés devraient permettre à l String.format
solution plus préférable.
byte
, de -128
a 127
, inclusivement
@Vivek : qu'est-ce qu'une "valeur extrêmement grande" ? Quelle est l'entrée et quelle est la sortie ?
Laissez-moi vous expliquer à nouveau... J'ai une collection de chaînes d'octets dans un tableau. Mais ce que je dois faire est d'analyser chaque octet séparément... Donc, je ne veux pas travailler sur l'ensemble du tableau, mais sur chaque chaîne d'octets à la fois, qui est un composant de ce tableau... La confusion est due au mot "tableau". Maintenant dans le code ci-dessous " byte bv = 10 ; String hexString = Integer.toHexString(bv) ; " CAse 1 (Byte Recieved : 68 Hex Output : : 44) Case : 2 (Byte Recieved : -46 Hex Output : : ffffffd2)......... Pourquoi est-ce que j'obtiens un résultat aussi inattendu pour certaines valeurs ?
@Vivek : lisez ma réponse au sujet de l'utilisation des toHexString
. Vous devez le masquer avec & 0xFF
c'est-à-dire Integer.toHexString(-46 & 0xFF)
es "d2"
.
Je poste cette question parce qu'aucune des réponses existantes n'explique pourquoi leurs approches fonctionnent, ce qui, à mon avis, est vraiment important pour ce problème. Dans certains cas, cela fait que la solution proposée semble inutilement compliquée et subtile. Pour illustrer mon propos, je vais proposer une approche assez simple, mais je vais fournir un peu plus de détails pour aider à l'illustrer pourquoi ça marche.
Tout d'abord, qu'est-ce qu'on essaie de faire ? Nous voulons convertir une valeur d'octet (ou un tableau d'octets) en une chaîne qui représente une valeur hexadécimale en ASCII. La première étape consiste donc à déterminer ce qu'est exactement un octet en Java :
Le type de données octet est un Nombre entier de complément à deux signé de 8 bits . Il a une valeur minimale de -128 et une valeur maximale de 127 (inclus). Le type de données byte peut être utile pour économiser de la mémoire dans les grands tableaux, où l'économie de mémoire est réellement importante. Ils peuvent également être utilisés à la place de int lorsque leurs limites aident à clarifier votre code ; le fait que la plage d'une variable soit limitée peut servir de documentation.
Qu'est-ce que cela signifie ? Plusieurs choses : Tout d'abord, et c'est le plus important, cela signifie que nous travaillons avec 8 bits . Ainsi, par exemple, nous pouvons écrire le nombre 2 sous la forme 0000 0010. Cependant, comme il s'agit d'un complément à deux, nous écrivons un 2 négatif comme ceci : 1111 1110. Ce que cela signifie également, c'est que la conversion en hexadécimal est très simple. Il suffit de convertir chaque segment de 4 bits directement en hexadécimal. Notez que pour comprendre les nombres négatifs dans ce schéma, vous devez d'abord comprendre le complément à deux. Si vous ne comprenez pas encore le complément à deux, vous pouvez lire une excellente explication ici : http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html
Une fois qu'un nombre est en complément à deux, il est très simple de le convertir en hexadécimal. En général, la conversion du binaire en hexadécimal est très simple, et comme vous le verrez dans les deux exemples suivants, vous pouvez passer directement du complément à deux à l'hexadécimal.
Exemple 1 : Convertir 2 en Hex.
1) Convertissez d'abord 2 en binaire en complément à deux :
2 (base 10) = 0000 0010 (base 2)
2) Maintenant, convertissez le binaire en hexadécimal :
0000 = 0x0 in hex
0010 = 0x2 in hex
therefore 2 = 0000 0010 = 0x02.
Exemple 2 : Convertir -2 (en complément à deux) en Hex.
1) Convertissez d'abord -2 en binaire en complément à deux :
-2 (base 10) = 0000 0010 (direct conversion to binary)
1111 1101 (invert bits)
1111 1110 (add 1)
therefore: -2 = 1111 1110 (in two's complement)
2) Maintenant, convertissez en Hex :
1111 = 0xF in hex
1110 = 0xE in hex
therefore: -2 = 1111 1110 = 0xFE.
Maintenant que nous avons abordé le concept, vous verrez que nous pouvons obtenir ce que nous voulons avec quelques masques et décalages simples. Ce qu'il faut comprendre, c'est que l'octet que vous essayez de convertir est déjà en complément à deux. Vous ne faites pas cette conversion vous-même. Je pense que c'est un point de confusion majeur sur cette question. Prenons par exemple le tableau d'octets suivant :
byte[] bytes = new byte[]{-2,2};
Nous venons de les convertir manuellement en hexagone, ci-dessus, mais comment le faire en Java ? Voici comment :
Étape 1 : Créer un StringBuffer pour contenir notre calcul.
StringBuffer buffer = new StringBuffer();
Étape 2 : Isolez les bits d'ordre supérieur, convertissez-les en hexadécimal, et ajoutez-les au tampon.
Étant donné le nombre binaire 1111 1110, nous pouvons isoler les bits d'ordre supérieur en les décalant d'abord de 4, puis en mettant à zéro le reste du nombre. Logiquement, c'est simple, mais les détails de mise en œuvre en Java (et dans de nombreux langages) introduisent un problème à cause de l'extension du signe. Essentiellement, lorsque vous décalez une valeur d'octet, Java convertit d'abord votre valeur en un nombre entier, puis effectue une extension de signe. Ainsi, alors que vous vous attendez à ce que 1111 1110 >> 4 soit 0000 1111, en réalité, en Java, cette valeur est représentée par le complément à deux 0xFFFFFFFF !
Revenons donc à notre exemple :
1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)
On peut alors isoler les bits avec un masque :
1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex.
En Java, nous pouvons faire tout cela en une seule fois :
Character.forDigit((bytes[0] >> 4) & 0xF, 16);
La fonction forDigit fait simplement correspondre le nombre que vous lui transmettez à l'ensemble des nombres hexadécimaux 0 à F.
Étape 3 : Ensuite, nous devons isoler les bits d'ordre inférieur. Puisque les bits que nous voulons sont déjà dans la bonne position, nous pouvons simplement les masquer :
1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.
Comme auparavant, en Java, nous pouvons faire tout cela en une seule fois :
Character.forDigit((bytes[0] & 0xF), 16);
En mettant tout cela ensemble, nous pouvons le faire comme une boucle for et convertir le tableau entier :
for(int i=0; i < bytes.length; i++){
buffer.append(Character.forDigit((bytes[i] >> 4) & 0xF, 16));
buffer.append(Character.forDigit((bytes[i] & 0xF), 16));
}
Nous espérons que cette explication rendra les choses plus claires pour ceux d'entre vous qui se demandent ce qui se passe exactement dans les nombreux exemples que vous trouverez sur Internet. J'espère ne pas avoir fait d'erreurs flagrantes, mais les suggestions et corrections sont les bienvenues !
Essayez de cette façon :
byte bv = 10;
String hexString = Integer.toHexString(bv);
Traitement des tableaux (si j'ai bien compris) :
byte[] bytes = {9, 10, 11, 15, 16};
StringBuffer result = new StringBuffer();
for (byte b : bytes) {
result.append(String.format("%02X ", b));
result.append(" "); // delimiter
}
return result.toString();
Comme l'a mentionné polygenelubricants, String.format()
est la bonne réponse par rapport à Integer.toHexString()
(car il traite les nombres négatifs de manière correcte).
Byte bv = 10 ; String hexString = Integer.toHexString(bv) ; Cela semble fonctionner Je peux l'appliquer individuellement sur chaque élément du tableau L'autre code (Dealing with array ) donne une valeur trop grande. Quelle pourrait en être la raison ?
@Vivek, c'est parce qu'en cas de bv
il renvoie un un seul caractère hexadécimal . Alors que le reste du code renvoie un chaîne de caractères hexadécimaux . J'ai changé le code avec le délimiteur pour que vous puissiez le comprendre maintenant.
Si vous voulez une représentation hexagonale de largeur constante, c'est-à-dire 0A
au lieu de A
afin de pouvoir récupérer les octets sans ambiguïté. format()
:
StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
result.append(String.format("%02X", bb));
}
return result.toString();
Si vous souhaitez utiliser une bibliothèque externe, la fonction org.apache.commons.codec.binary.Hex
La classe a un encodeHex
qui prend un byte[]
et renvoie un char[]
. Cette méthode est BEAUCOUP plus rapide que l'option format, et encapsule les détails de la conversion. Elle est également accompagnée d'un decodeHex
pour la conversion inverse.
Une méthode encore plus simple consiste à utiliser les fonctions intégrées javax.xml.bind.DatatypeConverter/parseHexBinary et printHexBinary. Voir stackoverflow.com/questions/9655181/
+1 à cette option. L'Hex possède également une méthode encodeHexString, qui prend un byte[] et renvoie un String.
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.
2 votes
Ce que vous appelez tableau d'octets en Java est appelé chaîne d'octets dans d'autres langages (par ex. docs.racket-lang.org/guide/bytestrings.html )