Convertendo uma String em Hexadecimal em Java

107

Estou tentando converter uma string como "teste123" em formato hexadecimal em java. Atualmente, estou usando o BlueJ.

E para convertê-lo de volta, é a mesma coisa, exceto para trás?


fonte
Por favor edite sua pergunta para mostrar o código você tem até agora . Você deve incluir pelo menos um esboço (mas de preferência um exemplo reproduzível mínimo ) do código com o qual está tendo problemas, então podemos tentar ajudar com o problema específico. Você também deve ler Como perguntar .
Toby Speight

Respostas:

201

Esta é uma maneira resumida de convertê-lo em hexadecimal:

public String toHex(String arg) {
    return String.format("%040x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
Kaleb Pederson
fonte
24
+1 para a amostra mais pura de 3vilness que já vi: usando um BigInteger para converter de um byte [] ...
Eduardo Costa
13
Adoro! Sem loops e sem mudança de bits. Eu quero dar a vocês
votos positivos de
5
para garantir 40 caracteres, você deve adicionar zero preenchimento: return String.format ("% 040x", new BigInteger (arg.getBytes (/ * YOUR_CHARSET? * /)));
Ron
4
@Kaleb Você tem idéia se possível converter a string resultante de volta? Se sim, você pode me dar algumas dicas? Obrigado!
artaxerxe
1
Você tem que usar o BigInteger(int,byte[])construtor; caso contrário, se o primeiro byte for negativo, você obterá um BigInteger negativo.
Joni
62

Para garantir que o hexadecimal tenha sempre 40 caracteres, o BigInteger deve ser positivo:

public String toHex(String arg) {
  return String.format("%x", new BigInteger(1, arg.getBytes(/*YOUR_CHARSET?*/)));
}
Jos Theeuwen
fonte
1
Este método é realmente o correto. Tente byte[] data = { -1, 1 };- o código nesta resposta funciona bem, enquanto aquele com 17 votos positivos falha.
hudolejev
1
É possível obter um byte com valor -1de uma string (como foi solicitado no exemplo)?
Kaleb Pederson
@KalebPederson Sim. Não é nem muito difícil. . Se a codificação escolhida alguma vez usar o bit mais significativo de qualquer caractere (digamos, como UTF- * do), você terá bytes negativos em seu array.
Ação judicial de Monica de
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
fonte
3
Interessante, se você não quer reinventar a roda.
Federico Zancan
3
@MelNicholson há uma função decodeHex em Hex para ir para um byte []. Você precisa usar isso porque nada garante que uma string HEX aleatória possa ser convertida em uma string em sua codificação.
BxlSofty
18

Os números que você codifica em hexadecimal devem representar alguma codificação dos caracteres, como UTF-8. Portanto, primeiro converta a string em um byte [] que representa a string nessa codificação e, em seguida, converta cada byte em 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
fonte
Esta é uma solução interessante e que atinge o cerne da representação digital de dados. Você poderia explicar o que está fazendo e o que os "números mágicos" em sua solução representam? Um recém-chegado pode não saber o que significa o operador >>>, por que usamos o bit a bit-and & junto com uma máscara de 0xF0, ou por que o array chars tem o tamanho [2 * buf.length].
Boris
16

Use DatatypeConverter.printHexBinary():

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

    return DatatypeConverter.printHexBinary(myBytes);
}

Exemplo de uso:

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

Impressões:

48656C6C6F20537461636B4F766572666C6F77

Nota : Isso causa um pequeno problema extra com Java 9e mais recentes, pois a API não é incluída por padrão. Para referência, por exemplo, consulte esta GitHub edição.

BullyWiiPlaza
fonte
11

Aqui uma outra solução

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
fonte
3
Legal, mas eu usaria format("%02x")então format () sempre usa 2 caracteres. Mesmo que ASCII seja hexadecimal de dois dígitos, ou seja, A = 0x65
mike jones
8

Todas as respostas baseadas em String.getBytes () envolvem a codificação de sua string de acordo com um Charset. Você não obtém necessariamente o valor hexadecimal dos caracteres de 2 bytes que compõem sua string. Se o que você realmente quer é o equivalente a um visualizador hexadecimal, você precisa acessar os caracteres diretamente. Esta é a função que uso em meu código para depurar problemas 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();
}

Em seguida, stringToHex ("testing123") fornecerá a você:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033
Bogdan Calmac
fonte
Isso é bom se o que você deseja é ver a representação interna dos caracteres Java, que é UTF-16, uma representação 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

Você pode retornar hexStringneste ponto, com a ressalva de que os caracteres nulos iniciais serão removidos e o resultado terá um comprimento ímpar se o primeiro byte for menor que 16. Se precisar lidar com esses casos, você pode adicionar algum código extra para preencher com 0s:

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

Para obter o valor inteiro de hex

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

Converta uma letra em código hexadecimal e um código hexadecimal em letras.

        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
fonte
5

Eu sugeriria algo assim, onde strestá sua string 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
fonte
Obrigado pela correção, Software Monkey. Eu estava muito cansado quando escrevi a resposta, e meu teste para 'raw [i] <= 9' é claramente insuficiente.
rodion
1
Isso funciona muito bem, existe uma maneira de reverter o hex gerado de volta para string novamente?
1
Onde está str nisso?
Viswanath Lekshmanan
3

Primeiro, converta-o em bytes usando a função getBytes () e depois converta-o em hexadecimal usando o seguinte:

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();
}
user2475511
fonte
3

Para ir na outra direção (hex para string), você pode usar

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

Converter String em Hexadecimal :

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

definitivamente esta é a maneira mais fácil.

Jorgesys
fonte
Isso não é uma solução. A questão é como obter a representação hexadecimal do conteúdo de uma String arbitrária e fornecer especificamente "testing123" como exemplo.
Skomisa
1

Usando a ajuda de vários povos de vários threads ..

Eu sei que isso foi respondido, mas gostaria de fornecer um método completo de codificação e decodificação para qualquer outro na minha mesma situação.

Aqui estão meus métodos de codificação e decodificação.

// 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
fonte
Agradável! Apenas na linha 13, ">>>" deve ser ">>"
spikeyang
0

Muito melhor:

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
fonte
0

Aqui estão alguns benchmarks que comparam diferentes abordagens e bibliotecas. O Guava vence o Apache Commons Codec na decodificação. Commons Codec vence Guava na codificação. E JHex supera ambos na decodificação e codificação.

Exemplo JHex

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

Tudo está em um único arquivo de classe para JHex . Sinta-se à vontade para copiar e colar se não quiser outra biblioteca em sua árvore de dependências. Observe também que ele está disponível apenas como jar Java 9 até que eu possa descobrir como publicar vários destinos de lançamento com o Gradle e o plug-in Bintray.

Jamespedwards42
fonte
0

Uma maneira curta e conveniente de converter uma String em sua notação hexadecimal é:

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
fonte
0

verifique esta solução para String para hex e hex para 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();
}

Saída da seguinte forma:

Limpar texto = testString para; 0181; with.love

Texto hexadecimal = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

Texto decodificado = testString para; 0181; with.love

Nitin Upadhyay
fonte