Conversión de una cadena a hexadecimal en Java

107

Estoy tratando de convertir una cadena como "testing123" en forma hexadecimal en java. Actualmente estoy usando BlueJ.

Y para convertirlo de nuevo, ¿es lo mismo excepto al revés?


fuente
Por favor, editar su pregunta para mostrar el código que tiene hasta ahora . Debe incluir al menos un esquema (pero preferiblemente un ejemplo mínimo reproducible ) del código con el que tiene problemas, luego podemos intentar ayudarlo con el problema específico. También debería leer Cómo preguntar .
Toby Speight

Respuestas:

201

Aquí hay una forma corta de convertirlo a hexadecimal:

public String toHex(String arg) {
    return String.format("%040x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
Kaleb Pederson
fuente
24
+1 a la muestra más pura de 3 maldad que he visto: usar un BigInteger para convertir de un byte [] ...
Eduardo Costa
13
¡Quiéralo! Sin bucles ni cambios de bits. Quiero darte 0xFF upvotes :)
laher
5
para asegurar 40 caracteres, debe agregar relleno de ceros: return String.format ("% 040x", new BigInteger (arg.getBytes (/ * YOUR_CHARSET? * /)));
Ron
4
@Kaleb ¿Tiene idea, si es posible, de volver a convertir la cadena resultante? Si es así, ¿puede darme algunas pistas? ¡Gracias!
artaxerxe
1
Tienes que usar el BigInteger(int,byte[])constructor; de lo contrario, si el primer byte es negativo, obtendrá un BigInteger negativo.
Joni
62

Para asegurarse de que el hexadecimal siempre tenga 40 caracteres, BigInteger debe ser positivo:

public String toHex(String arg) {
  return String.format("%x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
Jos Theeuwen
fuente
1
Este método es realmente el correcto. El byte[] data = { -1, 1 };código de prueba en esta respuesta funciona bien, mientras que el código de 17 votos a favor falla.
hudolejev
1
¿Es posible obtener un byte con valor -1de una cadena (como se solicitó en el ejemplo)?
Kaleb Pederson
@KalebPederson Sí. Ni siquiera es muy difícil. . Si la codificación elegida alguna vez usa el bit más significativo de cualquier carácter (digamos, como UTF- * do), tiene bytes negativos en su matriz.
Financia la demanda de Monica el
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

Joshua Swink
fuente
3
Interesante, si no quieres reinventar la rueda.
Federico Zancan
3
@MelNicholson hay una función decodeHex en Hex para ir a un byte []. Debe usar eso porque nada garantiza que una cadena HEX aleatoria se pueda convertir en una cadena en su codificación.
BxlSofty
18

Los números que codifique en hexadecimal deben representar alguna codificación de los caracteres, como UTF-8. Entonces, primero convierta la Cadena en un byte [] que representa la cadena en esa codificación, luego convierta cada byte en hexadecimal.

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);
}
Stephen Denne
fuente
Esta es una solución interesante y que ataca al núcleo de la representación digital de datos. Sin embargo, ¿podría explicar qué está haciendo y qué representan los "números mágicos" en su solución? Un recién llegado puede no saber qué significa el operador >>>, por qué usamos el bit a bit-and & junto con una máscara de 0xF0, o por qué la matriz de caracteres es de tamaño [2 * buf.length].
Boris
16

Utilizar DatatypeConverter.printHexBinary():

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

    return DatatypeConverter.printHexBinary(myBytes);
}

Uso de ejemplo:

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

Huellas dactilares:

48656C6C6F20537461636B4F766572666C6F77

Nota : Esto causa un pequeño problema adicional Java 9y más nuevo, ya que la API no está incluida de forma predeterminada. Para referencia, por ejemplo, consulte este GitHub número.

BullyWiiPlaza
fuente
11

Aqui otra solucion

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();
}
jordeu
fuente
3
Bien, pero usaría format("%02x")así que format () siempre usa 2 caracteres. A pesar de que ASCII es hexagonal de dos dígitos es decir, A = 0x65
Mike Jones
8

Todas las respuestas basadas en String.getBytes () implican codificar su cadena de acuerdo con un Charset. No necesariamente obtener el valor hexadecimal de los 2 bytes caracteres que componen su cadena. Si lo que realmente desea es el equivalente a un visor hexadecimal, debe acceder a los caracteres directamente. Aquí está la función que uso en mi código para depurar problemas de 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();
}

Entonces, stringToHex ("testing123") le dará:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033
Bogdan Calmac
fuente
Esto está bien si lo que desea es ver la representación interna de los caracteres Java, que es UTF-16, una representación específica de 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

Puede regresar hexStringen este punto, con la advertencia de que los caracteres nulos iniciales se eliminarán y el resultado tendrá una longitud impar si el primer byte es menor que 16. Si necesita manejar esos casos, puede agregar un código adicional rellenar con ceros:

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

Para obtener el valor entero de hexadecimal

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

Convierte una letra en código hexadecimal y código hexadecimal en letra.

        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);
Marcus Becker
fuente
5

Sugeriría algo como esto, donde strestá su cadena de entrada:

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());
}
Rodion
fuente
Gracias por la corrección, Software Monkey. Estaba bastante cansado cuando escribí la respuesta, y mi prueba para 'raw [i] <= 9' es claramente insuficiente.
rodion
1
Esto funciona realmente bien, ¿hay alguna manera de revertir el hexadecimal generado a la cadena nuevamente?
1
¿Dónde está str en esto?
Viswanath Lekshmanan
3

Primero conviértalo en bytes usando la función getBytes () y luego conviértalo en hexadecimal usando esto:

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();
}
usuario2475511
fuente
3

Para ir al revés (hexadecimal a cadena), puede usar

public String hexToString(String hex) {
    return new String(new BigInteger(hex, 16).toByteArray());
}
Jibby
fuente
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);
    }
}
Rowena Jiménez
fuente
1
new BigInteger(1, myString.getBytes(/*YOUR_CHARSET?*/)).toString(16)
ultraon
fuente
1

Convertir cadena a hexadecimal :

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

definitivamente esta es la manera fácil.

Jorgesys
fuente
Esta no es una solución. La pregunta es cómo obtener la representación hexadecimal del contenido de una cadena arbitraria, y se proporciona específicamente "testing123" como ejemplo.
skomisa
1

El uso de la ayuda de varios pueblos de varios subprocesos.

Sé que esto ha sido respondido, pero me gustaría dar un método de codificación y descodificación completo para cualquier otro en mi misma situación.

Aquí están mis métodos de codificación y decodificación ...

// 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;
}
Gadget Guru
fuente
¡Agradable! Solo en la línea 13, ">>>" debe ser ">>"
spikeyang
0

Mucho mejor:

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);
}
Dmitriy Bocharov
fuente
0

Aquí hay algunos puntos de referencia que comparan diferentes enfoques y bibliotecas. Guava supera a Apache Commons Codec en decodificación. Commons Codec supera a Guava en codificación. Y JHex los supera tanto en decodificación como en codificación.

Ejemplo de JHex

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

Todo está en un archivo de clase única para JHex . Siéntase libre de copiar y pegar si no desea otra biblioteca en su árbol de dependencias. También tenga en cuenta que solo está disponible como jar de Java 9 hasta que pueda descubrir cómo publicar múltiples destinos de lanzamiento con Gradle y el complemento Bintray.

jamespedwards42
fuente
0

Una forma breve y conveniente de convertir una cadena a su notación hexadecimal es:

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());
}
Amit Samuel
fuente
0

verifique esta solución para String to hex y hex to String vise-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();
}

Salida como sigue:

Texto claro = testString For; 0181; with.love

Texto hexadecimal = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

Texto decodificado = testString For; 0181; with.love

Nitin Upadhyay
fuente