J'ai un tableau d'octets rempli de nombres hexadécimaux et l'imprimer facilement est assez inutile car il existe de nombreux éléments non imprimables. J'ai besoin du code hexadécimal exact sous la forme de:3a5f771c
J'ai un tableau d'octets rempli de nombres hexadécimaux et l'imprimer facilement est assez inutile car il existe de nombreux éléments non imprimables. J'ai besoin du code hexadécimal exact sous la forme de:3a5f771c
Réponses:
D'après la discussion ici , et surtout cette réponse, voici la fonction que j'utilise actuellement:
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
Mes propres tests de performance minuscules (un million d'octets mille fois, 256 octets 10 millions de fois) ont montré qu'il était beaucoup plus rapide que toute autre alternative, environ la moitié du temps sur de longues matrices. Par rapport à la réponse dont je l'ai tirée, passer à des opérations au niveau du bit --- comme suggéré dans la discussion --- réduire d'environ 20% le temps pour les longues matrices. (Edit: Quand je dis que c'est plus rapide que les alternatives, je veux dire le code alternatif proposé dans les discussions. Les performances sont équivalentes à Commons Codec, qui utilise un code très similaire.)
Version 2k20, par rapport aux chaînes compactes Java 9:
private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
byte[] hexChars = new byte[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars, StandardCharsets.UTF_8);
}
String printHexBinary(byte[])
et byte[] parseHexBinary(String)
. printHexBinary
est, cependant, beaucoup (2x) plus lent que la fonction dans cette réponse. (J'ai vérifié la source; il utilise un stringBuilder
. parseHexBinary
Utilise un tableau.) Vraiment, cependant, pour la plupart des cas, c'est assez rapide et vous l'avez probablement déjà.
printHexBinary
?
javax.xml.bind.DataTypeConverter
est en cours de suppression de Java 11.
La bibliothèque Apache Commons Codec possède une classe Hex pour effectuer exactement ce type de travail.
import org.apache.commons.codec.binary.Hex;
String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
import org.apache.commons.codec.*;
vous pourriez le faireimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
avec cette méthode:String toHexString(byte[] data)
La méthode javax.xml.bind.DatatypeConverter.printHexBinary()
, qui fait partie de l' architecture Java pour la liaison XML (JAXB) , était un moyen pratique de convertir a byte[]
en chaîne hexadécimale. La DatatypeConverter
classe comprenait également de nombreuses autres méthodes de manipulation de données utiles.
Dans Java 8 et versions antérieures, JAXB faisait partie de la bibliothèque standard Java. Il a été déconseillé avec Java 9 et supprimé avec Java 11 , dans le cadre d'un effort pour déplacer tous les packages Java EE dans leurs propres bibliothèques. C'est une longue histoire . Maintenant, javax.xml.bind
n'existe pas, et si vous souhaitez utiliser JAXB, qui contient DatatypeConverter
, vous devrez installer l' API JAXB et JAXB Runtime de Maven.
Exemple d'utilisation:
byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);
Aura pour résultat:
000086003D
Cette réponse est la même que celle-ci .
Solution la plus simple, pas de bibliothèques externes, pas de constantes de chiffres:
public static String byteArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder(a.length * 2);
for(byte b: a)
sb.append(String.format("%02x", b));
return sb.toString();
}
Une solution Guava, pour être complet:
import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);
Maintenant hex
est "48656c6c6f20776f726c64"
.
new HashCode(bytes).toString()
.
HashCode.fromBytes(checksum).toString()
Ce simple oneliner fonctionne pour moi
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - L'utilisation de ceci supprimera les zéros non significatifs, mais bon pour mon cas d'utilisation. Merci @Voicu de l'avoir signalé
Voici quelques options courantes classées du simple (une ligne) au complexe (immense bibliothèque). Si vous êtes intéressé par les performances, consultez les micro-benchmarks ci-dessous.
Une solution très simple consiste à utiliser la BigInteger
représentation hexadécimale de:
new BigInteger(1, someByteArray).toString(16)
Notez que puisque cela gère les nombres et non les chaînes d'octets arbitraires, il omettra les zéros en tête - cela peut ou non être ce que vous voulez (par exemple 000AE3
vs 0AE3
pour une entrée de 3 octets). C'est également très lent, environ 100 fois plus lent que l'option suivante.
Voici un extrait de code complet, copiable et collable prenant en charge les majuscules / minuscules et l' endianisme . Il est optimisé pour minimiser la complexité de la mémoire et maximiser les performances et doit être compatible avec toutes les versions Java modernes (5+).
private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {
// our output size will be exactly 2x byte-array length
final char[] buffer = new char[byteArray.length * 2];
// choose lower or uppercase lookup table
final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;
int index;
for (int i = 0; i < byteArray.length; i++) {
// for little endian we count from last to first
index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;
// extract the upper 4 bit and look up char (0-A)
buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
// extract the lower 4 bit and look up char (0-A)
buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
}
return new String(buffer);
}
public static String encode(byte[] byteArray) {
return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}
Le code source complet avec licence et décodeur Apache v2 peut être trouvé ici .
En travaillant sur mon projet précédent, j'ai créé cette petite boîte à 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 décodeur / décodeur HEX très rapide et bien testé:
import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()
Vous pouvez le vérifier sur Github: bytes-java .
Bien sûr, il y a les bons codecs communs . ( avis d'avertissement à venir ) En travaillant sur le projet décrit ci-dessus, j'ai analysé le code et j'ai été très déçu; un grand nombre de codes non organisés en double, de codecs obsolètes et exotiques, probablement utiles uniquement pour très peu et des mises en œuvre trop complexes et lentes de codecs populaires (spécifiquement Base64). Je prendrais donc une décision éclairée si vous souhaitez l'utiliser ou une alternative. Quoi qu'il en soit, si vous souhaitez toujours l'utiliser, voici un extrait de code:
import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));
Le plus souvent, vous avez déjà la goyave comme dépendance. Si oui, utilisez simplement:
import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);
Si vous utilisez le framework Spring avec Spring Security, vous pouvez utiliser les éléments suivants:
import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));
Si vous utilisez déjà le cadre de sécurité Bouncy Castle, vous pouvez utiliser son Hex
util:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
Dans les versions précédentes de Java (8 et inférieures), le code Java pour JAXB était inclus en tant que dépendance d'exécution. Depuis la modularisation Java 9 et Jigsaw, votre code ne peut pas accéder à un autre code en dehors de son module sans déclaration explicite. Soyez donc conscient si vous obtenez une exception comme:
java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
lors de l'exécution sur une machine virtuelle Java avec Java 9+. Si c'est le cas, basculez les implémentations vers l'une des alternatives ci-dessus. Voir aussi cette question .
Voici les résultats d'un simple micro-benchmark JMH encodant des tableaux d'octets de différentes tailles . Les valeurs sont des opérations par seconde, donc plus c'est mieux. Notez que les micro-repères ne représentent souvent pas un comportement réel, alors prenez ces résultats avec un grain de sel.
| Name (ops/s) | 16 byte | 32 byte | 128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger | 2,088,514 | 1,008,357 | 133,665 | 4 |
| Opt2/3: Bytes Lib | 20,423,170 | 16,049,841 | 6,685,522 | 825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 | 529 |
| Opt5: Guava | 10,177,925 | 6,937,833 | 2,094,658 | 257 |
| Opt6: Spring | 18,704,986 | 13,643,374 | 4,904,805 | 601 |
| Opt7: BC | 7,501,666 | 3,674,422 | 1,077,236 | 152 |
| Opt8: JAX-B | 13,497,736 | 8,312,834 | 2,590,940 | 346 |
Spécifications: JDK 8u202, i7-7700K, Win10, 24 Go de RAM. Voir le benchmark complet ici .
Utiliser la classe DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
J'utiliserais quelque chose comme ça pour une longueur fixe, comme des hachages:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
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 que c'est celui-ci:
static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
final StringBuilder hex = new StringBuilder( 2 * raw.length );
for ( final byte b : raw ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
if (raw == null) return null
n'est pas un échec rapide. Pourquoi voudriez-vous jamais utiliser une null
clé?
Au moindre coût de stockage de la table de recherche, cette implémentation est simple et très rapide.
private static final char[] BYTE2HEX=(
"000102030405060708090A0B0C0D0E0F"+
"101112131415161718191A1B1C1D1E1F"+
"202122232425262728292A2B2C2D2E2F"+
"303132333435363738393A3B3C3D3E3F"+
"404142434445464748494A4B4C4D4E4F"+
"505152535455565758595A5B5C5D5E5F"+
"606162636465666768696A6B6C6D6E6F"+
"707172737475767778797A7B7C7D7E7F"+
"808182838485868788898A8B8C8D8E8F"+
"909192939495969798999A9B9C9D9E9F"+
"A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+
"B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+
"C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
"D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+
"E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+
"F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray();
;
public static String getHexString(byte[] bytes) {
final int len=bytes.length;
final char[] chars=new char[len<<1];
int hexIndex;
int idx=0;
int ofs=0;
while (ofs<len) {
hexIndex=(bytes[ofs++] & 0xFF)<<1;
chars[idx++]=BYTE2HEX[hexIndex++];
chars[idx++]=BYTE2HEX[hexIndex];
}
return new String(chars);
}
BYTE2HEX
tableau avec un for
cycle simple ?
static { }
bloc.
Que dis-tu de ça?
String byteToHex(final byte[] hash)
{
Formatter formatter = new Formatter();
for (byte b : hash)
{
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
Nous n'avons pas besoin d'utiliser de bibliothèque externe ou d'écrire du code basé sur des boucles et des constantes.
Est-ce suffisant:
byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);
Je préfère utiliser ceci:
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes, int offset, int count) {
char[] hexChars = new char[count * 2];
for ( int j = 0; j < count; j++ ) {
int v = bytes[j+offset] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
C'est une adaptation un peu plus souple de la réponse acceptée. Personnellement, je garde la réponse acceptée et cette surcharge avec elle, utilisable dans plus de contextes.
J'utilise généralement la méthode suivante pour l'instruction debuf, mais je ne sais pas si c'est la meilleure façon de le faire ou non
private static String digits = "0123456789abcdef";
public static String toHex(byte[] data){
StringBuffer buf = new StringBuffer();
for (int i = 0; i != data.length; i++)
{
int v = data[i] & 0xff;
buf.append(digits.charAt(v >> 4));
buf.append(digits.charAt(v & 0xf));
}
return buf.toString();
}
StringBuilder buf = new StringBuilder(data.length * 2);
.
Ok, donc il y a un tas de façons de le faire, mais si vous décidez d'utiliser une bibliothèque, je vous suggère de fouiller dans votre projet pour voir si quelque chose a été implémenté dans une bibliothèque qui fait déjà partie de votre projet avant d'ajouter une nouvelle bibliothèque juste pour faire ça. Par exemple, si vous n'avez pas déjà
org.apache.commons.codec.binary.Hex
vous avez peut-être ...
org.apache.xerces.impl.dv.util.HexBin
Si vous utilisez le framework Spring Security, vous pouvez utiliser:
import org.springframework.security.crypto.codec.Hex
final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
Ajouter un pot utilitaire pour une fonction simple n'est pas une bonne option. Assemblez plutôt vos propres classes d'utilitaires. ce qui suit est une mise en œuvre plus rapide possible.
public class ByteHex {
public static int hexToByte(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 String[] byteToHexTable = new String[]
{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
"B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
"C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
"E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
"F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
};
private static final String[] byteToHexTableLowerCase = new String[]
{
"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
"10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
"20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
"40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
"50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
"60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
"70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
"80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
"90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
"b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
"c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
"d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
"e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"
};
public static String byteToHex(byte b){
return byteToHexTable[b & 0xFF];
}
public static String byteToHex(byte[] bytes){
if(bytes == null) return null;
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
return sb.toString();
}
public static String byteToHex(short[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
return sb.toString();
}
public static String byteToHexLowerCase(byte[] bytes){
StringBuilder sb = new StringBuilder(bytes.length*2);
for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
return sb.toString();
}
public static byte[] hexToByte(String hexString) {
if(hexString == null) return null;
byte[] byteArray = new byte[hexString.length() / 2];
for (int i = 0; i < hexString.length(); i += 2) {
byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
}
return byteArray;
}
public static byte hexPairToByte(char ch1, char ch2) {
return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
}
}
Une petite variante de la solution proposée par @maybewecouldstealavan, qui vous permet de regrouper visuellement N octets ensemble dans la chaîne hexadécimale de sortie:
final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
final static char BUNDLE_SEP = ' ';
public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) {
char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)];
for (int j = 0, k = 1; j < bytes.length; j++, k++) {
int v = bytes[j] & 0xFF;
int start = (j * 2) + j/bundleSize;
hexChars[start] = HEX_ARRAY[v >>> 4];
hexChars[start + 1] = HEX_ARRAY[v & 0x0F];
if ((k % bundleSize) == 0) {
hexChars[start + 2] = BUNDLE_SEP;
}
}
return new String(hexChars).trim();
}
C'est:
bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E
bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E
Je ne trouve aucune solution sur cette page qui ne
Voici une solution qui n'a pas les défauts ci-dessus (aucune promesse que la mienne n'a pas d'autres défauts cependant)
import java.math.BigInteger;
import static java.lang.System.out;
public final class App2 {
// | proposed solution.
public static String encode(byte[] bytes) {
final int length = bytes.length;
// | BigInteger constructor throws if it is given an empty array.
if (length == 0) {
return "00";
}
final int evenLength = (int)(2 * Math.ceil(length / 2.0));
final String format = "%0" + evenLength + "x";
final String result = String.format (format, new BigInteger(bytes));
return result;
}
public static void main(String[] args) throws Exception {
// 00
out.println(encode(new byte[] {}));
// 01
out.println(encode(new byte[] {1}));
//203040
out.println(encode(new byte[] {0x20, 0x30, 0x40}));
// 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
out.println(encode("All your base are belong to us.".getBytes()));
}
}
Je ne pouvais pas obtenir cela sous 62 opcodes, mais si vous pouvez vivre sans remplissage 0 au cas où le premier octet est inférieur à 0x10, la solution suivante n'utilise que 23 opcodes. Montre vraiment comment des solutions «faciles à implémenter vous-même» comme «pad avec un zéro si la longueur de chaîne est impaire» peuvent devenir assez coûteuses si une implémentation native n'est pas déjà disponible (ou dans ce cas, si BigInteger avait la possibilité de préfixer avec des zéros dans toString).
public static String encode(byte[] bytes) {
final int length = bytes.length;
// | BigInteger constructor throws if it is given an empty array.
if (length == 0) {
return "00";
}
return new BigInteger(bytes).toString(16);
}
Ma solution est basée sur la solution peut-être de WeCouldStealAVan, mais ne repose sur aucune table de recherche allouée en plus. Il n'utilise pas de piratage `` int-to-char '' (en fait, le Character.forDigit()
fait, en effectuant une comparaison pour vérifier ce qu'est vraiment le chiffre) et peut donc être un peu plus lent. N'hésitez pas à l'utiliser où vous le souhaitez. À votre santé.
public static String bytesToHex(final byte[] bytes)
{
final int numBytes = bytes.length;
final char[] container = new char[numBytes * 2];
for (int i = 0; i < numBytes; i++)
{
final int b = bytes[i] & 0xFF;
container[i * 2] = Character.forDigit(b >>> 4, 0x10);
container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
}
return new String(container);
}
Si vous recherchez un tableau d'octets exactement comme celui-ci pour python, j'ai converti cette implémentation Java en python.
class ByteArray:
@classmethod
def char(cls, args=[]):
cls.hexArray = "0123456789ABCDEF".encode('utf-16')
j = 0
length = (cls.hexArray)
if j < length:
v = j & 0xFF
hexChars = [None, None]
hexChars[j * 2] = str( cls.hexArray) + str(v)
hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F)
# Use if you want...
#hexChars.pop()
return str(hexChars)
array = ByteArray()
print array.char(args=[])
Voici une java.util.Base64
implémentation de type (partielle), n'est-ce pas joli?
public class Base16/*a.k.a. Hex*/ {
public static class Encoder{
private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
private boolean upper;
public Encoder(boolean upper) {
this.upper=upper;
}
public String encode(byte[] data){
char[] value=new char[data.length*2];
char[] toHex=upper?toUpperHex:toLowerHex;
for(int i=0,j=0;i<data.length;i++){
int octet=data[i]&0xFF;
value[j++]=toHex[octet>>4];
value[j++]=toHex[octet&0xF];
}
return new String(value);
}
static final Encoder LOWER=new Encoder(false);
static final Encoder UPPER=new Encoder(true);
}
public static Encoder getEncoder(){
return Encoder.LOWER;
}
public static Encoder getUpperEncoder(){
return Encoder.UPPER;
}
//...
}
private static String bytesToHexString(byte[] bytes, int length) {
if (bytes == null || length == 0) return null;
StringBuilder ret = new StringBuilder(2*length);
for (int i = 0 ; i < length ; i++) {
int b;
b = 0x0f & (bytes[i] >> 4);
ret.append("0123456789abcdef".charAt(b));
b = 0x0f & bytes[i];
ret.append("0123456789abcdef".charAt(b));
}
return ret.toString();
}
Converts bytes data to hex characters
@param bytes byte array to be converted to hex string
@return byte String in hex format
private static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
int v;
for (int j = 0; j < bytes.length; j++) {
v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
toHexString(...)
méthode qui peut vous aider si c'est ce que vous recherchez.String.format(...)
Peut également faire quelques astuces de mise en forme soignées en utilisant la%2x
chaîne de code.