Comment faire pour convertir un tableau d'octets en une chaîne hexadécimale en Java?
J'ai un tableau d'octets rempli avec les nombres hexadécimaux et de l'imprimer le plus simple est assez inutile, car il existe de nombreux éléments non imprimables. Ce dont j'ai besoin est l'exact hexadécimal sous la forme de: 3a5f771c
- Pourquoi ne pas juste faire un essai d'abord nous montrer ce que vous avez. Vous n'avez rien à perdre et tout à gagner. Entier a une
toHexString(...)
méthode qui peut aider si c'est ce que vous cherchez. AussiString.format(...)
peut faire bien des astuces de mise en forme à l'aide de la%2x
chaîne de code. - double possible de En Java, comment puis-je convertir un tableau d'octets en une chaîne de chiffres hexadécimaux, tout en gardant les zéros?
- "Ce dont j'ai besoin est l'exact hexadécimal sous la forme de: 3a5f771c..." - vous avez demandé une forme exacte, mais vous n'avez pas de fournir un exemple précis. Va sur ce que vous avez fournis, convertir les quatre premiers octets d'une chaîne de caractères, puis concaténer les points de suspension à la chaîne.
- Avec l'aide de flux en Java 8, il peut simplement être mis en œuvre comme: static String byteArrayToHex(byte[] a) { return IntStream.range(0, un.la longueur) .mapToObj(i -> String.format("%02x", a[i])) .réduire((acc, v) -> acc + "" + v) .get(); }
Vous devez vous connecter pour publier un commentaire.
De la discussion ici, et surtout cette réponse, c'est la fonction que j'utilise actuellement:
Mon petit repères (un million d'octets d'un millier de fois, 256 octets de 10 millions de fois) ont montré qu'il est beaucoup plus rapide que n'importe quel autre, environ la moitié du temps sur le long de tableaux. Par rapport à la réponse je l'ai pris de, le passage à la bit-à-bit de la fpo --- comme il est suggéré dans la discussion --- réduire d'environ 20% du temps pour les longs tableaux. (Edit: Quand je dis que c'est plus rapide que les autres solutions, je veux dire le code alternatif offert dans les discussions. La Performance est l'équivalent de Communes Codec, qui utilise le même code.)
String printHexBinary(byte[])
etbyte[] parseHexBinary(String)
.printHexBinary
est, cependant, beaucoup (2x) plus lent que la fonction de cette réponse. (J'ai vérifié la source; il utilise unstringBuilder
.parseHexBinary
utilise un tableau.) Vraiment, si, pour la plupart des fins, elle est assez rapide et vous avez probablement déjà.printHexBinary
?String.format("%0" + (bytes.length << 1) + "X", new BigInteger(1, bytes));
mais la performance était de la foutaise. C'est une bien meilleure solution.n * 2
à être utilisé dans le premier tableau de l'index, puis++n
dans le second accès.javax.xml.bind.DataTypeConverter
est retiré de Java 11.& 0xFF
nécessaire dans cette ligneint v = bytes[j] & 0xFF;
? Ai-je raté quelque chose ou est-ce inutile?int v
: Le négatif octet sera élargie - l'int sera plein de bits. Vous auriez pas demander l'index de tableau 15, mais quelque chose dans les millions.bytes.length * 3
,hexChars[j * 3]
,hexChars[j * 3 + 1]
ethexChars[j * 3 + 2] = 0x20
La Apache Commons Codec la bibliothèque dispose d'un Hex classe pour faire ce genre de travail.
import org.apache.commons.codec.*;
vous pourriez faireimport org.apache.commons.codec.binary.Hex;
commons-codec-1.9.jar
258 Kio, et je suppose que l'espace d'impact peut aller plus loin si vous allez utiliser Proguard ou quelque chose comme ça.org.bouncycastle.util.encoders.Hex
, avec cette méthode :String toHexString(byte[] data)
La méthode
javax.xml.bind.DatatypeConverter.printHexBinary()
, une partie de la Java Architecture for XML Binding (JAXB), était un moyen pratique pour convertir unbyte[]
chaîne hexadécimale. LeDatatypeConverter
classe également inclus de nombreuses autres données utiles méthodes de manipulation.Dans Java 8 et les versions antérieures, JAXB faisait partie de la Java standard de la bibliothèque. Il a été obsolète avec Java 9 et supprimé avec Java 11, dans le cadre d'un effort pour déplacer tous les Java EE des paquets dans leurs propres bibliothèques. C'est une longue histoire. Maintenant,
javax.xml.bind
n'existe pas, et si vous voulez utiliser JAXB, qui contientDatatypeConverter
, vous aurez besoin pour installer le API JAXB et JAXB d'Exécution de Maven.Exemple d'utilisation:
Permettra:
Que cette réponse est la même que cette une.
Solution la plus simple, pas de libs externes, pas de chiffres constantes:
Une Goyave solution, par souci d'exhaustivité:
Maintenant
hex
est"48656c6c6f20776f726c64"
.new HashCode(bytes).toString()
.HashCode.fromBytes(checksum).toString()
Cette simple oneliner fonctionne pour moi
String result = new BigInteger(1, inputBytes).toString(16);
MODIFIER - grâce à cette volonté de supprimer les zéros, mais bon fonctionné pour mon cas d'utilisation. Merci @Voicu pour le pointant hors
Utilisation DataTypeConverter classe
javax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
J'ai trouvé trois façons différentes ici:
http://www.rgagnon.com/javadetails/java-0596.html
Le plus élégant, comme il le note également, je pense, est celui-ci:
if (raw == null) return null
n'est pas échouer rapidement. Pourquoi voudriez-vous jamais utiliser unnull
clé?Je voudrais utiliser quelque chose comme ceci pour une durée déterminée, comme les hachages:
Au petit coût de stockage de la table de recherche de cette mise en œuvre est simple et très rapide.
BYTE2HEX
tableau avec une simplefor
cycle?static { }
bloc.Voici quelques options commandées à partir de la simple (one-liner) aux plus complexes (l'immense bibliothèque). Si vous êtes intéressé par les performances, voir la micro-benchmarks ci-dessous.
Option 1: extrait de Code - Simple
Une solution très simple est d'utiliser le
BigInteger
's représentation hexadécimale:Noter que depuis cette poignées numéros de pas arbitraire octet-chaînes il va ignorer les zéros en tête - cela peut ou peut ne pas être ce que vous voulez (par exemple
000AE3
vs0AE3
pour un 3 octet d'entrée). C'est aussi très lent, sur 100x plus lent par rapport à l'option suivante.Option 2: extrait de Code Avancé
Ici est un complet, copie & pasteable extrait du code de l'appui majuscules/minuscules et stockage. Il est optimisé pour minimiser la mémoire de la complexité et de maximiser la performance et devrait être compatible avec tous les versions de Java (5+).
Le code source complet avec Apache v2 licence et le décodeur peut être trouvé ici.
Option 3: à l'Aide d'une petite bibliothèque optimisée: octets-java
Tout en travaillant sur mon projet précédent, j'ai créé cette petite trousse d'outils pour travailler avec des octets en Java. Il n'a pas de dépendances externes et est compatible avec Java 7+. Il comprend, entre autres, un très rapide et bien testé HEX fr/décodeur:
Vous pouvez le vérifier sur Github: octets-java.
Option 4: Apache Commons Codec
Bien sûr il y a le bon vieux communes codecs. (d'alerte de l'opinion à l'avance) Tout en travaillant sur le projet décrit ci-dessus j'ai analysé le code et a été très déçu; beaucoup de double non-syndiqués code, obsolète et exotiques codecs probablement utile uniquement pour de très rares et tout à fait sur d'ingénierie et de ralentir les implémentations de populaires codecs (plus précisément en Base64). Par conséquent, je voudrais prendre une décision éclairée si vous voulez les utiliser, ou d'un autre. De toute façon, si vous voulez continuer à l'utiliser, voici un extrait de code:
Option 5: Google Goyave
Plus souvent que vous ne possédez pas déjà Goyave comme une dépendance. Si juste utiliser:
Option 6: Le Printemps De Sécurité
Si vous utilisez le Spring framework avec Printemps De Sécurité vous pouvez utiliser les éléments suivants:
Option 7: Château Gonflable
Si vous utilisez déjà le cadre de la sécurité Château Gonflable vous pouvez utiliser ses
Hex
util:Pas Vraiment l'Option 8: Java 9+ Compatibilité ou "Ne Pas Utiliser JAXBs javax/xml/bind/DatatypeConverter'
Précédentes de Java (8 et ci-dessous) versions du code Java pour JAXB a été inclus à titre d'exécution de la dépendance. Depuis Java 9 et Jigsaw modularisation votre code ne peut pas accéder à un autre code à l'extérieur du module sans déclaration explicite. Donc, être conscient que si vous obtenez une exception comme:
lors de l'exécution sur une machine virtuelle java avec Java 9+. Si oui, alors l'interrupteur implémentations à l'une des alternatives ci-dessus. Voir aussi ce question.
Micro Repères
Voici les résultats à partir d'un simple JMH micro de référence de l'encodage tableaux d'octets de différentes tailles. Les valeurs sont des opérations par seconde, de sorte plus c'est mieux.
Notez que les micro-benchmarks, très souvent, ne représentent pas le monde réel comportement, afin de prendre ces résultats avec un grain de sel.
Spécifications: JDK 8u202, i7-7700K, Win10, 24GO de Ram. Voir l'intégralité de l'indice de référence ici.
Comment à ce sujet?
Je préfère utiliser ce:
Il est légèrement plus grande souplesse d'adaptation de la accepté de répondre.
Personnellement, je garde les deux accepté de répondre et cette surcharge avec elle, utilisable dans d'autres contextes.
J'ai l'habitude d'utiliser la méthode suivante pour debuf déclaration, mais je ne sais pas si c'est la meilleure façon de faire ou de ne pas
StringBuilder buf = new StringBuilder(data.length * 2);
.Ok, donc il y a des tas de façons de le faire, mais si vous décidez d'utiliser une bibliothèque je suggère de fouiller dans votre projet pour voir si quelque chose a été mis en place dans une bibliothèque qui fait déjà partie de votre projet avant d'ajouter une nouvelle bibliothèque juste pour ce faire. Par exemple, si vous ne l'avez pas déjà
peut-être que vous avez...
Si vous utilisez le Printemps du cadre de la Sécurité, vous pouvez utiliser:
L'ajout d'un utilitaire jar pour simple fonction n'est pas une bonne option. Au lieu d'assembler des classes utilitaires. la suite est possible, la mise en œuvre rapide.
Une petite variante de la solution proposée par @maybewecouldstealavan, qui vous permet de visuellement faisceau de N octets ensemble en sortie de chaîne hexadécimale:
Qui est:
Ne trouve pas de solution sur cette page qui n'a pas
Voici une solution qui n'a pas les défauts ci-dessus(pas de promesses, mine de ne pas avoir d'autres défauts tout de même)
Je ne pouvais pas obtenir ce en vertu de 62 opcodes, mais si vous pouvez vivre sans le 0 de rembourrage dans le cas où le premier octet est inférieur à 0x10, alors la solution suivante utilise seulement 23 opcodes. Vraiment montre comment "facile à mettre en œuvre vous-même des solutions comme "pad avec un zéro si la longueur de la chaîne est impair" peut être assez cher si un natif de la mise en œuvre n'est pas déjà disponible(ou dans ce cas, si BigInteger avait l'option de préfixe avec des zéros dans les toString).
Ma solution est basée sur maybeWeCouldStealAVan de la solution, mais ne repose pas sur les plus affectés tables de recherche. Il n'utilise aucun "int-à-char" jette hacks (en fait,
Character.forDigit()
t-il, de l'exécution de certains de comparaison pour vérifier ce que le chiffre est vraiment) et donc peut-être un peu plus lent. N'hésitez pas à utiliser où vous le souhaitez. Des acclamations.//Décalage d'octets est plus efficace
//Vous pouvez l'utiliser trop
Si vous êtes à la recherche d'un tableau d'octets exactement comme cela pour python, j'ai converti cette implémentation Java en python.
Ici est un
java.util.Base64
-comme la mise en œuvre(partielle), n'est-il pas assez?