Chuyển đổi một chuỗi thành hệ thập lục phân trong Java


107

Tôi đang cố chuyển đổi một chuỗi như "testing123" thành dạng thập lục phân trong java. Tôi hiện đang sử dụng BlueJ.

Và để chuyển đổi nó trở lại, nó có giống nhau ngoại trừ lùi lại không?

java  string  hex 

Vui lòng chỉnh sửa câu hỏi của bạn để hiển thị mã bạn có cho đến nay . Bạn nên bao gồm ít nhất một phác thảo (nhưng tốt nhất là một ví dụ có thể tái tạo tối thiểu ) về mã mà bạn đang gặp sự cố, sau đó chúng tôi có thể cố gắng trợ giúp vấn đề cụ thể. Bạn cũng nên đọc Cách hỏi .
Toby Speight

Câu trả lời:


201

Đây là một cách ngắn gọn để chuyển nó thành hex:

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

24
+1 đến mẫu 3vilness thuần túy nhất mà tôi từng thấy: sử dụng BigInteger để chuyển đổi từ một byte [] ...
Eduardo Costa

13
Yêu nó! Không có vòng lặp và không lật bit. Tôi muốn cung cấp cho bạn 0xFF lượt
ủng hộ

5
để đảm bảo 40 Ký tự, bạn nên thêm zero padding: return String.format ("% 040x", new BigInteger (arg.getBytes (/ * YOUR_CHARSET? * /)));
Ron

4
@Kaleb Bạn có biết nếu có thể chuyển đổi lại Chuỗi kết quả không? Nếu, có, bạn có thể cho tôi một số gợi ý? Cảm ơn!
artaxerxe

1
Bạn phải sử dụng hàm BigInteger(int,byte[])tạo; ngược lại nếu byte đầu tiên là số âm, bạn sẽ nhận được BigInteger âm.
Joni

62

Để đảm bảo rằng hệ lục phân luôn dài 40 ký tự, BigInteger phải là số dương:

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

1
Phương pháp này thực sự là một trong những chính xác. Hãy thử byte[] data = { -1, 1 };- mã trong câu trả lời này hoạt động tốt, trong khi đó với 17 phiếu ủng hộ không thành công.
hudolejev

1
Có thể lấy một byte có giá trị -1ra khỏi một chuỗi (như được yêu cầu trong ví dụ) không?
Kaleb Pederson

@KalebPederson Có. Nó thậm chí không khó lắm. . Nếu bạn chọn mã hóa bao giờ sử dụng các bit quan trọng nhất của bất kỳ ký tự (ví dụ như UTF- * làm), bạn có âm bytes trong mảng của bạn.
Vụ kiện của Fund Monica

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
Thật thú vị, nếu bạn không muốn phát minh lại bánh xe.
Federico Zancan,

3
@MelNicholson có một hàm decodeHex trong Hex để chuyển đến một byte []. Bạn cần sử dụng điều đó vì không có gì đảm bảo rằng một chuỗi HEX ngẫu nhiên có thể được chuyển đổi thành một chuỗi trong mã hóa của bạn.
BxlSofty

18

Các số mà bạn mã hóa thành hệ thập lục phân phải đại diện cho một số mã hóa của các ký tự, chẳng hạn như UTF-8. Vì vậy, trước tiên hãy chuyển đổi Chuỗi thành một byte [] đại diện cho chuỗi trong bảng mã đó, sau đó chuyển đổi từng byte sang hệ thập lục phâ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);
}

Đây là một giải pháp thú vị và là một giải pháp cốt lõi của việc biểu diễn dữ liệu kỹ thuật số. Bạn có thể vui lòng giải thích những gì bạn đang làm và "những con số kỳ diệu" trong giải pháp của bạn đại diện cho điều gì không? Người mới có thể không biết toán tử >>> nghĩa là gì, tại sao chúng ta sử dụng bitwise-and & cùng với mặt nạ 0xF0, hoặc tại sao mảng ký tự có kích thước [2 * buf.length].
Boris

16

Sử dụng DatatypeConverter.printHexBinary():

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

    return DatatypeConverter.printHexBinary(myBytes);
}

Ví dụ sử dụng:

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

Bản in:

48656C6C6F20537461636B4F766572666C6F77

Lưu ý : Điều này gây ra thêm một chút rắc rối với Java 9và mới hơn vì API không được bao gồm theo mặc định. Để tham khảo ví dụ như thấy này GitHub vấn đề.


11

Đây là một giải pháp khác

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
Tốt nhưng tôi sẽ sử dụng format("%02x")để định dạng () luôn sử dụng 2 ký tự. Mặc dù ASCII là đôi chữ số hex tức là A = 0x65
mike jones

8

Tất cả các câu trả lời dựa trên String.getBytes () liên quan đến việc mã hóa chuỗi của bạn theo một Charset. Bạn không nhất thiết phải nhận giá trị hex của các ký tự 2 byte tạo nên chuỗi của bạn. Nếu những gì bạn thực sự muốn tương đương với một trình xem hex, thì bạn cần truy cập trực tiếp vào các ký tự. Đây là chức năng mà tôi sử dụng trong mã của mình để gỡ lỗi các vấn đề 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();
}

Sau đó, stringToHex ("testing123") sẽ cung cấp cho bạn:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033

Điều này là tốt nếu những gì bạn muốn là xem biểu diễn bên trong của các ký tự Java, đó là UTF-16, một biểu diễn cụ thể của 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

Bạn có thể quay lại hexStringtại thời điểm này, với cảnh báo rằng các ký tự null đứng đầu sẽ bị loại bỏ và kết quả sẽ có độ dài kỳ lạ nếu byte đầu tiên nhỏ hơn 16. Nếu bạn cần xử lý những trường hợp đó, bạn có thể thêm một số mã bổ sung để đệm bằng các số 0:

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

5

Để nhận giá trị Integer của hex

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

5

Chuyển đổi một chữ cái trong mã hex và mã hex trong chữ cái.

        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

Tôi sẽ đề xuất một cái gì đó như thế này, strchuỗi đầu vào của bạn ở đâu :

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

Cảm ơn vì đã sửa, Software Monkey. Tôi đã khá mệt mỏi khi viết câu trả lời và bài kiểm tra 'raw [i] <= 9' của tôi rõ ràng là không đủ.
rodion

1
Điều này hoạt động thực sự tốt, có cách nào để đảo ngược hex đã tạo trở lại chuỗi một lần nữa không?

1
Str ở đâu trong này?
Viswanath Lekshmanan

3

Đầu tiên chuyển nó thành byte bằng cách sử dụng hàm getBytes () và sau đó chuyển nó thành hex usign như sau:

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

Để đi theo cách khác (hex thành chuỗi), bạn có thể sử dụng

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

Chuyển đổi chuỗi thành hệ thập lục phân :

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

chắc chắn đây là cách dễ dàng.


Đây không phải là một giải pháp. Câu hỏi đặt ra là làm thế nào để lấy biểu diễn hex cho nội dung của một Chuỗi tùy ý và được cung cấp cụ thể "testing123" làm ví dụ.
skomisa

1

Sử dụng sự trợ giúp của Nhiều người từ nhiều Chủ đề ..

Tôi biết điều này đã được trả lời, nhưng tôi muốn cung cấp phương pháp mã hóa & giải mã đầy đủ cho bất kỳ người nào khác trong trường hợp tương tự của tôi ..

Đây là phương pháp Mã hóa & Giải mã của tôi ..

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

Đẹp! Chỉ trên đường 13, ">>>" nên được ">>"
spikeyang

0

Tốt hơn nhiều:

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

Dưới đây là một số điểm chuẩn so sánh các phương pháp tiếp cận và thư viện khác nhau. Ổi đánh bại Apache Commons Codec khi giải mã. Commons Codec đánh bại Guava khi mã hóa. Và JHex đánh bại chúng cả về giải mã và mã hóa.

Ví dụ về JHex

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

Mọi thứ đều nằm trong một tệp lớp duy nhất cho JHex . Hãy sao chép dán nếu bạn chưa muốn có một thư viện khác trong cây phụ thuộc của mình. Cũng lưu ý, nó chỉ khả dụng dưới dạng jar Java 9 cho đến khi tôi có thể tìm ra cách xuất bản nhiều mục tiêu phát hành với Gradle và plugin Bintray.


0

Một cách ngắn gọn và thuận tiện để chuyển đổi một Chuỗi sang ký hiệu Hệ thập lục phân của nó là:

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

kiểm tra giải pháp này cho Chuỗi thành hex và hex thành Chuỗi ngược lại

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

Đầu ra như sau:

Clear Text = testString For; 0181; with.love

Văn bản hệ lục phân = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

Văn bản được giải mã = ​​testString For; 0181; with.love

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.