การแปลงสตริงเป็นเลขฐานสิบหกใน Java


107

ฉันกำลังพยายามแปลงสตริงเช่น "testing123" เป็นรูปแบบฐานสิบหกใน java ฉันกำลังใช้ BlueJ

แล้วแปลงกลับมันเหมือนกันไหมยกเว้นย้อนกลับ?

java  string  hex 

โปรดแก้ไขคำถามของคุณเพื่อแสดงรหัสที่คุณมีจนถึงตอนนี้ คุณควรใส่เค้าโครงอย่างน้อย (แต่ควรเป็นตัวอย่างที่สามารถทำซ้ำได้น้อยที่สุด ) ของโค้ดที่คุณประสบปัญหาจากนั้นเราจะพยายามช่วยแก้ปัญหานั้น ๆ คุณควรอ่านวิธีถามด้วย
Toby Speight

คำตอบ:


201

นี่เป็นวิธีสั้น ๆ ในการแปลงเป็นฐานสิบหก:

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

24
+1 ถึงตัวอย่าง 3vilness ที่บริสุทธิ์ที่สุดที่ฉันเคยเห็น: การใช้ BigInteger เพื่อแปลงจากไบต์ [] ...
Eduardo Costa

13
รักเลย! ไม่มีลูปและไม่พลิกบิต ฉันต้องการเพิ่มคะแนน
โหวต

5
เพื่อให้แน่ใจว่ามีอักขระ 40 ตัวคุณควรเพิ่มช่องว่างภายใน: return String.format ("% 040x", BigInteger ใหม่ (arg.getBytes (/ * YOUR_CHARSET? * /)));
รอน

4
@Kaleb คุณคิดว่าถ้าเป็นไปได้ที่จะแปลง String ที่เป็นผลลัพธ์กลับมาหรือไม่? ถ้าใช่คุณช่วยบอกฉันหน่อยได้ไหม ขอบคุณ!
artaxerxe

1
คุณต้องใช้ตัวBigInteger(int,byte[])สร้าง; มิฉะนั้นถ้าไบต์แรกเป็นลบคุณจะได้รับ BigInteger ที่เป็นลบ
Joni

62

เพื่อให้แน่ใจว่าฐานสิบหกมีความยาว 40 อักขระเสมอ BigInteger จะต้องเป็นค่าบวก:

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

1
วิธีนี้เป็นวิธีที่ถูกต้องจริงๆ ลองbyte[] data = { -1, 1 };- รหัสในคำตอบนี้ใช้งานได้ดีในขณะที่การโหวต 17 ครั้งล้มเหลว
hudolejev

1
เป็นไปได้ไหมที่จะได้รับไบต์ที่มีค่า-1จากสตริง (ตามที่ขอในตัวอย่าง)
Kaleb Pederson

@KalebPederson ใช่. มันไม่ได้ยากมาก . หากคุณเลือกการเข้ารหัสที่เคยใช้บิตที่สำคัญที่สุดของตัวอักษรใด ๆ (พูดเหมือน UTF- * ทำ) คุณมีเชิงลบbyteในอาร์เรย์ของคุณ
คดีของ 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
น่าสนใจถ้าคุณไม่ต้องการสร้างล้อใหม่
Federico Zancan

3
@MelNicholson มีฟังก์ชัน decodeHex ใน Hex เพื่อไปยังไบต์ [] คุณจำเป็นต้องใช้สิ่งนั้นเนื่องจากไม่มีอะไรรับประกันได้ว่าสตริง HEX แบบสุ่มสามารถแปลงเป็นสตริงในการเข้ารหัสของคุณได้
BxlSofty

18

ตัวเลขที่คุณเข้ารหัสเป็นเลขฐานสิบหกต้องแสดงถึงการเข้ารหัสอักขระบางตัวเช่น UTF-8 ดังนั้นก่อนอื่นให้แปลง String เป็นไบต์ [] แทนสตริงในการเข้ารหัสนั้นจากนั้นแปลงแต่ละไบต์เป็นเลขฐานสิบหก

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

นี่เป็นวิธีการแก้ปัญหาที่น่าสนใจและเป็นส่วนสำคัญของการนำเสนอข้อมูลแบบดิจิทัล คุณช่วยอธิบายได้ไหมว่าคุณกำลังทำอะไรอยู่และ "ตัวเลขวิเศษ" ในโซลูชันของคุณแสดงถึงอะไร ผู้มาใหม่อาจไม่ทราบว่าตัวดำเนินการ >>> หมายถึงอะไรทำไมเราถึงใช้ bitwise-and & พร้อมกับมาสก์ 0xF0 หรือทำไมอาร์เรย์ตัวอักษรจึงมีขนาด [2 * buf.length]
Boris

16

ใช้DatatypeConverter.printHexBinary():

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

    return DatatypeConverter.printHexBinary(myBytes);
}

ตัวอย่างการใช้งาน:

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

พิมพ์:

48656C6C6F20537461636B4F766572666C6F77

หมายเหตุ : สิ่งนี้ทำให้เกิดปัญหาเพิ่มเติมเล็กน้อยJava 9และใหม่กว่าเนื่องจากไม่รวม API โดยค่าเริ่มต้น สำหรับการอ้างอิงเช่นเห็นนี้ GitHubปัญหา


11

นี่คือทางออกอื่น ๆ

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
ดี แต่ฉันจะใช้format("%02x")ดังนั้น format () จะใช้ 2 ตัวอักษรเสมอ แม้ว่า ASCII จะเป็นเลขฐานสิบหกสองหลักเช่น A = 0x65
mike jones

8

คำตอบทั้งหมดตาม String.getBytes () เกี่ยวข้องกับการเข้ารหัสสตริงของคุณตาม Charset คุณไม่จำเป็นต้องได้รับค่าฐานสิบหกของ 2 ไบต์ตัวละครที่ทำขึ้นสายของคุณ หากสิ่งที่คุณต้องการจริงเทียบเท่ากับโปรแกรมดูเลขฐานสิบหกคุณต้องเข้าถึงตัวอักษรโดยตรง นี่คือฟังก์ชั่นที่ฉันใช้ในรหัสของฉันสำหรับการดีบักปัญหา 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();
}

จากนั้น stringToHex ("testing123") จะให้คุณ:

0074 0065 0073 0074 0069 006e 0067 0031 0032 0033

สิ่งนี้ใช้ได้ดีหากสิ่งที่คุณต้องการคือการดูการแสดงภายในของอักขระ Java ซึ่งก็คือ UTF-16 ซึ่งเป็นการแสดงเฉพาะของ 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

คุณสามารถกลับมาhexStringที่จุดนี้ได้โดยมีข้อแม้ว่าตัวอักษร null ที่นำหน้าจะถูกตัดออกและผลลัพธ์จะมีความยาวเป็นคี่หากไบต์แรกน้อยกว่า 16 หากคุณต้องการจัดการกับกรณีเหล่านั้นคุณสามารถเพิ่มโค้ดพิเศษได้ เพื่อรองด้วย 0s:

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

5

เพื่อรับค่าจำนวนเต็มของฐานสิบหก

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

5

แปลงตัวอักษรในรหัสฐานสิบหกและรหัสฐานสิบหกเป็นตัวอักษร

        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

ฉันขอแนะนำสิ่งนี้strสตริงอินพุตของคุณอยู่ที่ไหน:

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

ขอบคุณสำหรับการแก้ไข Software Monkey ฉันค่อนข้างเหนื่อยเมื่อเขียนคำตอบและการทดสอบ 'raw [i] <= 9' ก็ไม่เพียงพออย่างชัดเจน
rodion

1
มันใช้งานได้ดีจริงๆมีวิธีย้อนกลับ hex ที่สร้างขึ้นกลับไปเป็นสตริงอีกครั้งหรือไม่?

1
str อยู่ที่ไหนในนี้?
Viswanath Lekshmanan

3

ก่อนอื่นให้แปลงเป็นไบต์โดยใช้ฟังก์ชัน getBytes () จากนั้นแปลงเป็นเลขฐานสิบหกใช้สิ่งนี้:

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

หากต้องการไปอีกทางหนึ่ง (เลขฐานสิบหกเป็นสตริง) คุณสามารถใช้

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

แปลงสตริงเป็นเลขฐานสิบหก :

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

แน่นอนว่านี่เป็นวิธีง่ายๆ


นี่ไม่ใช่วิธีแก้ปัญหา คำถามคือถามว่าจะรับการแสดงเลขฐานสิบหกของเนื้อหาของสตริงตามอำเภอใจได้อย่างไรและระบุ"testing123"โดยเฉพาะเป็นตัวอย่าง
skomisa

1

การใช้ความช่วยเหลือหลายคนจากหลายเธรด ..

ฉันรู้ว่าได้รับคำตอบแล้ว แต่ฉันอยากจะให้วิธีเข้ารหัสและถอดรหัสแบบเต็มสำหรับคนอื่น ๆ ในสถานการณ์เดียวกันของฉัน ..

นี่คือวิธีการเข้ารหัสและถอดรหัสของฉัน ..

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

ดี! เฉพาะบรรทัดที่ 13 ">>>" ควรเป็น ">>"
spikeyang

0

ดีกว่ามาก:

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

นี่คือเกณฑ์มาตรฐานบางส่วนที่เปรียบเทียบแนวทางและไลบรารีต่างๆ ฝรั่งเต้น Apache Commons Codec ที่ถอดรหัส Commons Codec เอาชนะ Guava ที่การเข้ารหัส และ JHex เอาชนะทั้งการถอดรหัสและการเข้ารหัส

ตัวอย่าง JHex

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

ทุกอย่างอยู่ในไฟล์ชั้นเดียวสำหรับ JHex อย่าลังเลที่จะคัดลอกวางหากคุณไม่ต้องการห้องสมุดอื่นในแผนผังการพึ่งพาของคุณ นอกจากนี้โปรดทราบว่ามันพร้อมใช้งานใน Java 9 jar เท่านั้นจนกว่าฉันจะสามารถหาวิธีเผยแพร่เป้าหมายการเผยแพร่หลายรายการด้วย Gradle และปลั๊กอิน Bintray ได้


0

วิธีที่สั้นและสะดวกในการแปลง String เป็นสัญกรณ์เลขฐานสิบหกคือ:

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 to hex และ hex ถึง 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();
}

ผลลัพธ์ดังนี้:

Clear Text = testString For; 0181; with.love

ข้อความเลขฐานสิบหก = 74657374537472696e6720466f723b303138313b776974682e6c6f7665

ข้อความถอดรหัส = testString สำหรับ; 0181; with.love

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.