Java'da Bir Dizeyi Onaltılı Biçime Dönüştürme


107

Java'da "testing123" gibi bir dizeyi onaltılık biçime dönüştürmeye çalışıyorum. Şu anda BlueJ kullanıyorum.

Ve onu geri dönüştürmek, geriye doğru hariç aynı şey mi?

java  string  hex 

Lütfen şu ana kadar sahip olduğunuz kodu gösterecek şekilde sorunuzu düzenleyin . Sorun yaşadığınız kodun en azından bir taslağını (ancak tercihen asgari yeniden üretilebilir bir örneğini ) eklemelisiniz , ardından belirli bir soruna yardımcı olmaya çalışabiliriz. Ayrıca Nasıl Sorulur'u da okumalısınız .
Toby Speight

Yanıtlar:


201

İşte onu hex'e dönüştürmenin kısa bir yolu:

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

24
Şimdiye kadar gördüğüm en saf 3 kötülük örneğine +1: bir bayttan dönüştürmek için bir BigInteger kullanma [] ...
Eduardo Costa

13
Sevdim! Döngü yok ve bit çevirme yok. Sana 0xFF olumlu oyları vermek istiyorum :)
laher

5
40 Karakter sağlamak için sıfır dolgu eklemelisiniz: return String.format ("% 040x", yeni BigInteger (arg.getBytes (/ * YOUR_CHARSET? * /)));
Ron

4
@Kaleb Eğer mümkünse String'i geri dönüştürmek için bir fikriniz var mı? Evet ise, bana bazı ipuçları verebilir misiniz? Teşekkürler!
artaxerxe

1
Yapıcıyı kullanmanız gerekir BigInteger(int,byte[]); aksi takdirde, ilk bayt negatifse, negatif bir BigInteger elde edersiniz.
Joni

62

Hex'in her zaman 40 karakter uzunluğunda olmasını sağlamak için, BigInteger pozitif olmalıdır:

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

1
Bu yöntem aslında doğru olanıdır. Dene byte[] data = { -1, 1 };- bu cevaptaki kod iyi çalışıyor, oysa 17 olumlu oyla başarısız oluyor.
hudolejev

1
-1Bir dizeden değeri olan bir bayt elde etmek mümkün müdür (örnekte talep edildiği gibi)?
Kaleb Pederson

@KalebPederson Evet. Hatta çok da zor değil. . Senin kodlayan seçilenin varsa hiç herhangi bir karakterin en önemli biti kullanır (UTF-gibi, diyelim * do), negatif olması byteda dizideki s.
Fund Monica'nın Davası

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
Tekerleği yeniden icat etmek istemiyorsanız ilginç.
Federico Zancan

3
@MelNicholson Hex'te bir bayta [] gitmek için bir decodeHex işlevi vardır. Bunu kullanmanız gerekir, çünkü kodlamanızda rastgele bir HEX dizesinin bir dizeye dönüştürülebileceğini hiçbir şey garanti etmez.
BxlSofty

18

Onaltılık olarak kodladığınız sayılar, UTF-8 gibi karakterlerin bazı kodlamalarını temsil etmelidir. Öyleyse önce String'i o kodlamadaki dizeyi temsil eden bir bayta [] dönüştürün, ardından her bir baytı onaltılıya dönüştürün.

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);
}

Bu ilginç bir çözümdür ve verilerin dijital temsilinin özünde yer alan bir çözümdür. Lütfen ne yaptığınızı ve çözümünüzdeki "sihirli sayıların" neyi temsil ettiğini açıklar mısınız? Yeni gelen bir kullanıcı, >>> operatörünün ne anlama geldiğini, neden bitwise-ve & ile birlikte 0xF0 maskesini kullandığımızı veya karakter dizisinin neden [2 * buf.length] boyutunda olduğunu bilemeyebilir.
Boris

16

Kullanım DatatypeConverter.printHexBinary():

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

    return DatatypeConverter.printHexBinary(myBytes);
}

Örnek kullanım:

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

Baskılar:

48656C6C6F20537461636B4F766572666C6F77

Not : Bu Java 9, API varsayılan olarak dahil edilmediğinden biraz daha fazla soruna ve daha yenisine neden olur . Referans için örneğin bu GitHub konuya bakın .


11

İşte başka bir çözüm

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
Güzel ama format("%02x")format () her zaman 2 karakter kullanır. ASCII çift haneli onaltılık olmasına rağmen, yani A = 0x65
mike jones

8

String.getBytes () 'e dayalı tüm yanıtlar, dizenizi bir Karakter kümesine göre kodlamayı içerir . Dizenizi oluşturan 2 baytlık karakterlerin onaltılık değerini almanız gerekmez . Aslında istediğiniz şey bir onaltılık görüntüleyiciye eşdeğerse, karakterlere doğrudan erişmeniz gerekir. Kodumda Unicode sorunlarını ayıklamak için kullandığım işlev:

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

Daha sonra stringToHex ("testing123") size şunları verecektir:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033

Unicode'un belirli bir temsili olan UTF-16 olan Java karakterlerinin dahili temsilini görmek istediğinizde bu sorun değil.
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

hexStringBu noktada, baştaki boş karakterlerin çıkarılacağı uyarısı ile geri dönebilirsiniz ve ilk bayt 16'dan az ise sonuç tek bir uzunluğa sahip olacaktır. Bu durumları halletmeniz gerekiyorsa, fazladan kod ekleyebilirsiniz. 0'larla doldurmak için:

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

5

Onaltılık Tamsayı değerini almak için

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

5

Onaltılık koddaki bir harfi harf olarak onaltılık kodu dönüştürün.

        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

Bunun gibi bir şey öneririm str, giriş dizeniz nerede :

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

Düzeltme için teşekkürler, Yazılım Maymunu. Cevabı yazarken oldukça yorgundum ve 'ham [i] <= 9' testim açıkça yetersiz.
rodion

1
Bu gerçekten iyi çalışıyor, oluşturulan onaltılık dizeyi tekrar dizeye döndürmenin bir yolu var mı?

1
Str bunun neresinde?
Viswanath Lekshmanan

3

Önce getBytes () işlevini kullanarak onu bayta dönüştürün ve sonra bunu hex usign'a dönüştürün:

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

Diğer yöne gitmek için (onaltılık dizeye), kullanabilirsiniz

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

Dizeyi Onaltılık Biçime Dönüştür :

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

kesinlikle bu kolay yoldur.


Bu bir çözüm değil. Soru, rastgele bir String'in içeriğinin onaltılık gösteriminin nasıl elde edileceğini soruyor ve özellikle örnek olarak "test123" sağladı .
skomisa

1

Birden Fazla Kişi yardımını birden çok Konu'dan kullanma ..

Bunun yanıtlandığını biliyorum, ancak aynı durumdaki diğer kişiler için tam bir kodlama ve kod çözme yöntemi vermek istiyorum ..

İşte Kodlama ve Kod Çözme yöntemlerim ..

// 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;
}

Güzel! Yalnızca 13. satırdaki ">>>" ">>" olmalıdır
spikeyang

0

Çok daha iyi:

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

İşte farklı yaklaşımları ve kitaplıkları karşılaştıran bazı karşılaştırmalar . Guava, kod çözmede Apache Commons Codec'i yener. Commons Codec, kodlamada Guava'yı yener. Ve JHex, hem kod çözme hem de kodlama için onları yener.

JHex örneği

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

JHex için her şey tek bir sınıf dosyasındadır . Bağımlılık ağacınızda henüz başka bir kitaplık istemiyorsanız, kopyalayıp yapıştırmaktan çekinmeyin. Ayrıca, Gradle ve Bintray eklentisi ile birden fazla sürüm hedefini nasıl yayınlayacağımı bulana kadar yalnızca Java 9 jar olarak kullanılabilir olduğunu unutmayın.


0

Bir Stringi Onaltılık gösterimine dönüştürmenin kısa ve kullanışlı bir yolu şudur:

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

String'den hex'e ve hex'den String'e tam tersi için bu çözümü kontrol edin

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

Çıktı aşağıdaki gibidir:

Metni Temizle = testString For; 0181; with.love

Onaltılı Metin = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

Kodu Çözülmüş Metin = testString For; 0181; with.love

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.