Conversion d'une chaîne en hexadécimal en Java


107

J'essaye de convertir une chaîne comme "testing123" en forme hexadécimale en java. J'utilise actuellement BlueJ.

Et pour le reconvertir, est-ce la même chose sauf à l'envers?

java  string  hex 

Veuillez modifier votre question pour afficher le code que vous avez jusqu'à présent . Vous devez inclure au moins un aperçu (mais de préférence un exemple reproductible minimal ) du code avec lequel vous rencontrez des problèmes, puis nous pouvons essayer de vous aider avec le problème spécifique. Vous devriez également lire Comment demander .
Toby Speight

Réponses:


201

Voici un court moyen de le convertir en hexadécimal:

public String toHex(String arg) {
    return String.format("%040x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}

24
+1 à l'échantillon le plus pur de 3vilness que j'ai jamais vu: utiliser un BigInteger pour convertir à partir d'un octet [] ...
Eduardo Costa

13
Aimer! Pas de boucles et pas de retournement de bits. Je veux vous donner des votes positifs 0xFF :)
laher

5
pour garantir 40 caractères, vous devez ajouter un remplissage nul: return String.format ("% 040x", new BigInteger (arg.getBytes (/ * YOUR_CHARSET? * /)));
Ron

4
@Kaleb Avez-vous une idée si possible de reconvertir la chaîne obtenue? Si oui, pouvez-vous me donner quelques indices? Merci!
artaxerxe

1
Vous devez utiliser le BigInteger(int,byte[])constructeur; sinon, si le premier octet est négatif, vous obtenez un BigInteger négatif.
Joni

62

Pour garantir que l'hexagone comporte toujours 40 caractères, le BigInteger doit être positif:

public String toHex(String arg) {
  return String.format("%x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}

1
Cette méthode est en fait la bonne. Essayez byte[] data = { -1, 1 };- le code dans cette réponse fonctionne bien, alors que celui avec 17 votes positifs échoue.
hudolejev

1
Est-il possible d'obtenir un octet avec une valeur -1dans une chaîne (comme cela a été demandé dans l'exemple)?
Kaleb Pederson le

@KalebPederson Oui. Ce n'est même pas très dur. . Si votre choix encodage jamais utilise le bit le plus important de tout caractère ( par exemple, comme UTF- * faire), vous avez négatif bytes dans votre tableau.
Fund Monica's Lawsuit

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

String hexString = Hex.encodeHexString(myString.getBytes(/* charset */));

http://commons.apache.org/codec/apidocs/org/apache/commons/codec/binary/Hex.html


3
Intéressant, si vous ne voulez pas réinventer la roue.
Federico Zancan

3
@MelNicholson il y a une fonction decodeHex dans Hex pour aller à un octet []. Vous devez l'utiliser car rien ne garantit qu'une chaîne HEX aléatoire puisse être convertie en une chaîne dans votre encodage.
BxlSofty

18

Les nombres que vous encodez en hexadécimal doivent représenter un certain encodage des caractères, tel que UTF-8. Commencez par convertir la chaîne en un octet [] représentant la chaîne dans ce codage, puis convertissez chaque octet en hexadécimal.

public static String hexadecimal(String input, String charsetName) throws UnsupportedEncodingException {
    if (input == null) throw new NullPointerException();
    return asHex(input.getBytes(charsetName));
}

private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

public static String asHex(byte[] buf)
{
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i)
    {
        chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
        chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    }
    return new String(chars);
}

C'est une solution intéressante et qui frappe au cœur de la représentation numérique des données. Pourriez-vous s'il vous plaît expliquer ce que vous faites, et ce que représentent les «nombres magiques» dans votre solution? Un nouveau venu peut ne pas savoir ce que signifie l'opérateur >>>, pourquoi nous utilisons les bits et & avec un masque de 0xF0, ou pourquoi le tableau chars est de taille [2 * buf.length].
Boris

16

Utilisez DatatypeConverter.printHexBinary():

public static String toHexadecimal(String text) throws UnsupportedEncodingException
{
    byte[] myBytes = text.getBytes("UTF-8");

    return DatatypeConverter.printHexBinary(myBytes);
}

Exemple d'utilisation:

System.out.println(toHexadecimal("Hello StackOverflow"));

Impressions:

48656C6C6F20537461636B4F766572666C6F77

Remarque : cela pose un petit problème supplémentaire avec Java 9et plus récent car l'API n'est pas incluse par défaut. Pour référence, par exemple, consultez ce GitHub numéro.


11

Voici une autre solution

public static String toHexString(byte[] ba) {
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < ba.length; i++)
        str.append(String.format("%x", ba[i]));
    return str.toString();
}

public static String fromHexString(String hex) {
    StringBuilder str = new StringBuilder();
    for (int i = 0; i < hex.length(); i+=2) {
        str.append((char) Integer.parseInt(hex.substring(i, i + 2), 16));
    }
    return str.toString();
}

3
Bien mais j'utiliserais format("%02x")donc format () utilise toujours 2 caractères. Même si ASCII est hexadécimal à deux chiffres, c'est-à-dire A = 0x65
Mike

8

Toutes les réponses basées sur String.getBytes () impliquent l' encodage de votre chaîne selon un Charset. Vous ne recevez pas nécessairement la valeur hexadécimale des 2 octets caractères qui composent votre chaîne. Si ce que vous voulez réellement est l'équivalent d'un visualiseur hexadécimal, vous devez accéder directement aux caractères. Voici la fonction que j'utilise dans mon code pour déboguer les problèmes Unicode:

static String stringToHex(String string) {
  StringBuilder buf = new StringBuilder(200);
  for (char ch: string.toCharArray()) {
    if (buf.length() > 0)
      buf.append(' ');
    buf.append(String.format("%04x", (int) ch));
  }
  return buf.toString();
}

Ensuite, stringToHex ("testing123") vous donnera:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033

C'est bien si vous voulez voir la représentation interne des caractères Java, qui est UTF-16, une représentation spécifique d'Unicode.
Jonathan Rosenne

5
byte[] bytes = string.getBytes(CHARSET); // you didn't say what charset you wanted
BigInteger bigInt = new BigInteger(bytes);
String hexString = bigInt.toString(16); // 16 is the radix

Vous pouvez revenir hexStringà ce stade, avec la mise en garde que les caractères NULL de début seront supprimés, et le résultat aura une longueur impaire si le premier octet est inférieur à 16. Si vous devez gérer ces cas, vous pouvez ajouter du code supplémentaire pour compléter avec des 0:

StringBuilder sb = new StringBuilder();
while ((sb.length() + hexString.length()) < (2 * bytes.length)) {
  sb.append("0");
}
sb.append(hexString);
return sb.toString();

5

Pour obtenir la valeur Integer de hex

        //hex like: 0xfff7931e to int
        int hexInt = Long.decode(hexString).intValue();

5

Convertissez une lettre en code hexadécimal et un code hexadécimal en lettre.

        String letter = "a";
    String code;
    int decimal;

    code = Integer.toHexString(letter.charAt(0));
    decimal = Integer.parseInt(code, 16);

    System.out.println("Hex code to " + letter + " = " + code);
    System.out.println("Char to " + code + " = " + (char) decimal);

5

Je suggérerais quelque chose comme ceci, où se strtrouve votre chaîne d'entrée:

StringBuffer hex = new StringBuffer();
char[] raw = tokens[0].toCharArray();
for (int i=0;i<raw.length;i++) {
    if     (raw[i]<=0x000F) { hex.append("000"); }
    else if(raw[i]<=0x00FF) { hex.append("00" ); }
    else if(raw[i]<=0x0FFF) { hex.append("0"  ); }
    hex.append(Integer.toHexString(raw[i]).toUpperCase());
}

Merci pour la correction, Software Monkey. J'étais assez fatigué quand j'ai écrit la réponse, et mon test pour «raw [i] <= 9» est clairement insuffisant.
rodion

1
Cela fonctionne vraiment bien, y a-t-il un moyen d'inverser à nouveau l'hexagone généré en chaîne?

1
Où est str ici?
Viswanath Lekshmanan

3

Convertissez-le d'abord en octets en utilisant la fonction getBytes (), puis convertissez-le en hexadécimal en utilisant ceci:

private static String hex(byte[] bytes) {
    StringBuilder sb = new StringBuilder();
    for (int i=0; i<bytes.length; i++) {
        sb.append(String.format("%02X ",bytes[i]));
    }
    return sb.toString();
}

3

Pour aller dans l'autre sens (hex à chaîne), vous pouvez utiliser

public String hexToString(String hex) {
    return new String(new BigInteger(hex, 16).toByteArray());
}

1
import java.io.*;
import java.util.*;

public class Exer5{

    public String ConvertToHexadecimal(int num){
        int r;
        String bin="\0";

        do{
            r=num%16;
            num=num/16;

            if(r==10)
            bin="A"+bin;

            else if(r==11)
            bin="B"+bin;

            else if(r==12)
            bin="C"+bin;

            else if(r==13)
            bin="D"+bin;

            else if(r==14)
            bin="E"+bin;

            else if(r==15)
            bin="F"+bin;

            else
            bin=r+bin;
        }while(num!=0);

        return bin;
    }

    public int ConvertFromHexadecimalToDecimal(String num){
        int a;
        int ctr=0;
        double prod=0;

        for(int i=num.length(); i>0; i--){

            if(num.charAt(i-1)=='a'||num.charAt(i-1)=='A')
            a=10;

            else if(num.charAt(i-1)=='b'||num.charAt(i-1)=='B')
            a=11;

            else if(num.charAt(i-1)=='c'||num.charAt(i-1)=='C')
            a=12;

            else if(num.charAt(i-1)=='d'||num.charAt(i-1)=='D')
            a=13;

            else if(num.charAt(i-1)=='e'||num.charAt(i-1)=='E')
            a=14;

            else if(num.charAt(i-1)=='f'||num.charAt(i-1)=='F')
            a=15;

            else
            a=Character.getNumericValue(num.charAt(i-1));
            prod=prod+(a*Math.pow(16, ctr));
            ctr++;
        }
        return (int)prod;
    }

    public static void main(String[] args){

        Exer5 dh=new Exer5();
        Scanner s=new Scanner(System.in);

        int num;
        String numS;
        int choice;

        System.out.println("Enter your desired choice:");
        System.out.println("1 - DECIMAL TO HEXADECIMAL             ");
        System.out.println("2 - HEXADECIMAL TO DECIMAL              ");
        System.out.println("0 - EXIT                          ");

        do{
            System.out.print("\nEnter Choice: ");
            choice=s.nextInt();

            if(choice==1){
                System.out.println("Enter decimal number: ");
                num=s.nextInt();
                System.out.println(dh.ConvertToHexadecimal(num));
            }

            else if(choice==2){
                System.out.println("Enter hexadecimal number: ");
                numS=s.next();
                System.out.println(dh.ConvertFromHexadecimalToDecimal(numS));
            }
        }while(choice!=0);
    }
}

1
new BigInteger(1, myString.getBytes(/*YOUR_CHARSET?*/)).toString(16)

1

Convertir la chaîne en hexadécimal :

public String hexToString(String hex) {
    return Integer.toHexString(Integer.parseInt(hex));
}

c'est certainement le moyen le plus simple.


Ce n'est pas une solution. La question est de savoir comment obtenir la représentation hexadécimale du contenu d'une chaîne arbitraire, et a spécifiquement fourni "testing123" comme exemple.
skomisa

1

Utilisation de l'aide de plusieurs personnes à partir de plusieurs threads.

Je sais que cela a été répondu, mais je voudrais donner une méthode complète d'encodage et de décodage pour tous les autres dans la même situation.

Voici mes méthodes d'encodage et de décodage.

// Global Charset Encoding
public static Charset encodingType = StandardCharsets.UTF_8;

// Text To Hex
public static String textToHex(String text)
{
    byte[] buf = null;
    buf = text.getBytes(encodingType);
    char[] HEX_CHARS = "0123456789abcdef".toCharArray();
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i)
    {
        chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
        chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    }
    return new String(chars);
}

// Hex To Text
public static String hexToText(String hex)
{
    int l = hex.length();
    byte[] data = new byte[l / 2];
    for (int i = 0; i < l; i += 2)
    {
        data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
            + Character.digit(hex.charAt(i + 1), 16));
    }
    String st = new String(data, encodingType);
    return st;
}

Agréable! Uniquement sur la ligne 13, ">>>" devrait être ">>"
spikeyang

0

Bien mieux:

public static String fromHexString(String hex, String sourceEncoding ) throws  IOException{
    ByteArrayOutputStream bout = new ByteArrayOutputStream();
    byte[] buffer = new byte[512];
    int _start=0;
    for (int i = 0; i < hex.length(); i+=2) {
        buffer[_start++] = (byte)Integer.parseInt(hex.substring(i, i + 2), 16);
        if (_start >=buffer.length || i+2>=hex.length()) {
            bout.write(buffer);
            Arrays.fill(buffer, 0, buffer.length, (byte)0);
            _start  = 0;
        }
    }

    return  new String(bout.toByteArray(), sourceEncoding);
}

0

Voici quelques points de repère comparant différentes approches et bibliothèques. Guava bat le codec Apache Commons au décodage. Le codec Commons bat Guava lors de l'encodage. Et JHex les bat à la fois pour le décodage et l'encodage.

Exemple JHex

String hexString = "596f752772652077656c636f6d652e";
byte[] decoded = JHex.decodeChecked(hexString);
System.out.println(new String(decoded));
String reEncoded = JHex.encode(decoded);

Tout est dans un fichier de classe unique pour JHex . N'hésitez pas à copier-coller si vous ne souhaitez pas encore une autre bibliothèque dans votre arborescence de dépendances. Notez également qu'il n'est disponible qu'en tant que jar Java 9 jusqu'à ce que je sache comment publier plusieurs cibles de publication avec Gradle et le plugin Bintray.


0

Un moyen court et pratique de convertir une chaîne en sa notation hexadécimale est:

public static void main(String... args){
String str = "Hello! This is test string.";
char ch[] = str.toCharArray();
StringBuilder sb = new StringBuilder();
    for (int i = 0; i < ch.length; i++) {
        sb.append(Integer.toHexString((int) ch[i]));
    }
    System.out.println(sb.toString());
}

0

vérifiez cette solution pour String to hex et hex to String vice-versa

public class TestHexConversion {
public static void main(String[] args) {
    try{
        String clearText = "testString For;0181;with.love";
        System.out.println("Clear Text  = " + clearText);
        char[] chars = clearText.toCharArray();
        StringBuffer hex = new StringBuffer();
        for (int i = 0; i < chars.length; i++) {
            hex.append(Integer.toHexString((int) chars[i]));
        }
        String hexText = hex.toString();
        System.out.println("Hex Text  = " + hexText);
        String decodedText = HexToString(hexText);
        System.out.println("Decoded Text = "+decodedText);
    } catch (Exception e){
        e.printStackTrace();
    }
}

public static String HexToString(String hex){

      StringBuilder finalString = new StringBuilder();
      StringBuilder tempString = new StringBuilder();

      for( int i=0; i<hex.length()-1; i+=2 ){
          String output = hex.substring(i, (i + 2));
          int decimal = Integer.parseInt(output, 16);
          finalString.append((char)decimal);
          tempString.append(decimal);
      }
    return finalString.toString();
}

Sortie comme suit:

Clear Text = testString For; 0181; with.love

Texte hexadécimal = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

Texte décodé = testString For; 0181; with.love

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.