Konversi representasi string dari dump hex ke array byte menggunakan Java?

372

Saya mencari cara untuk mengkonversi string panjang (dari dump), yang mewakili nilai hex menjadi array byte.

Saya tidak bisa mengutarakannya lebih baik daripada orang yang memposting pertanyaan yang sama di sini .

Tetapi untuk tetap asli, saya akan mengucapkannya dengan cara saya sendiri: seandainya saya memiliki string "00A0BF"yang ingin saya tafsirkan sebagai

byte[] {0x00,0xA0,0xBf}

apa yang harus saya lakukan?

Saya seorang pemula Java dan akhirnya menggunakan BigIntegerdan mengawasi untuk memimpin nol nol. Tapi saya pikir itu jelek dan saya yakin saya kehilangan sesuatu yang sederhana.

rafraf
sumber
Saya telah menjinakkan di BigInteger sini .
John McClane
FWIW String.getBytes()tidak akan berfungsi seperti yang Anda pikirkan. Harus belajar ini dengan cara yang sulit. if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

Jawaban:

636

Inilah solusi yang menurut saya lebih baik daripada yang diposting sejauh ini:

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

Alasan mengapa ini merupakan peningkatan:

  • Aman dengan nol di depan (tidak seperti BigInteger) dan dengan nilai byte negatif (tidak seperti Byte.parseByte)

  • Tidak mengubah String menjadi char[], atau membuat objek StringBuilder dan String untuk setiap byte tunggal.

  • Tidak ada dependensi perpustakaan yang mungkin tidak tersedia

Jangan ragu untuk menambahkan pemeriksaan argumen melalui assertatau pengecualian jika argumen tersebut tidak diketahui aman.

Dave L.
sumber
2
Bisakah Anda memberikan contoh yang diterjemahkan salah, atau menjelaskan bagaimana itu salah?
Dave L.
5
Tidak berfungsi untuk String "0". Itu melempar java.lang.StringIndexOutOfBoundsException
ovdsrn
49
"0" bukan input yang valid. Byte membutuhkan masing-masing dua digit heksidecimal. Seperti jawabannya, "Jangan ragu untuk menambahkan pemeriksaan argumen ... jika argumen tersebut tidak diketahui aman."
Dave L.
12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString) tampaknya sekitar 20% lebih cepat daripada solusi di atas dalam tes mikro saya (untuk berapa pun nilainya), serta melemparkan dengan benar pengecualian pada input yang tidak valid (misalnya "gg" bukan hexString yang valid tetapi akan mengembalikan -77 menggunakan solusi seperti yang diusulkan).
Trevor Freeman
6
@DaedalusAlpha Tergantung pada konteks Anda, tetapi biasanya saya merasa lebih baik gagal cepat dan keras dengan hal-hal seperti itu sehingga Anda dapat memperbaiki asumsi Anda daripada diam-diam mengembalikan data yang salah.
Dave L.
331

Satu baris:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Peringatan :

  • di Java 9 Jigsaw ini bukan lagi bagian dari set root java.se (default) sehingga akan menghasilkan ClassNotFoundException kecuali Anda menentukan --add-modules java.se.ee (terima kasih kepada @ eckes)
  • Tidak tersedia di Android (terima kasih Fabianatas perhatiannya), tetapi Anda dapat mengambil kode sumber jika sistem Anda kekurangan javax.xmlkarena beberapa alasan. Terima kasih kepada @ Bert Regelinkuntuk mengekstraksi sumbernya.
Vladislav Rastrusny
sumber
14
IMHO ini harus diterima / jawaban atas karena itu pendek dan cleanish (tidak seperti @ jawaban Davel) dan tidak memerlukan libs eksternal (seperti jawaban skaffman ini). Juga, <Masukkan lelucon usang tentang menciptakan kembali sepeda> .
Priidu Neemre
9
kelas datatypeconverter tidak tersedia di android misalnya.
Fabian
4
Peringatan: di Java 9 Jigsaw ini bukan lagi bagian dari java.seset root (default) sehingga akan menghasilkan ClassNotFoundExceptionkecuali Anda tentukan--add-modules java.se.ee
eckes
2
@dantebarba Saya pikir javax.xml.bind.DatatypeConvertersudah menyediakan metode untuk encoding / decoding data Base64. Lihat parseBase64Binary()dan printBase64Binary().
DragShot
2
Untuk menambah masalah DataTypeConverter, Java SE 11 telah menghapus sepenuhnya API JAXB dan sekarang hanya disertakan dengan Java EE. Anda juga dapat menambahkannya sebagai ketergantungan Maven, seperti yang disarankan di sini: stackoverflow.com/a/43574427/7347751
David Mordigal
79

Kelas Hex di commons-codec harus melakukan itu untuk Anda.

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF
skaffman
sumber
6
Ini juga terlihat bagus. Lihat org.apache.commons.codec.binary.Hex.decodeHex ()
Dave L.
Itu menarik. Tetapi saya menemukan solusi mereka sulit untuk diikuti. Apakah ada kelebihan dibandingkan dengan apa yang Anda usulkan (selain memeriksa bahkan jumlah karakter)?
rafraf
38

Anda sekarang dapat menggunakan BaseEncoding di guavauntuk mencapai hal ini.

BaseEncoding.base16().decode(string);

Untuk membalikkannya gunakan

BaseEncoding.base16().encode(bytes);
jontro
sumber
27

Sebenarnya, saya pikir solusi BigInteger sangat bagus:

new BigInteger("00A0BF", 16).toByteArray();

Sunting: Tidak aman untuk memimpin nol , seperti yang dicatat oleh poster.

Dave L.
sumber
Saya juga berpikir begitu pada awalnya. Dan terima kasih telah mendokumentasikannya - saya hanya berpikir saya harus ... itu melakukan beberapa hal aneh meskipun saya tidak benar-benar mengerti - seperti menghilangkan beberapa 0x00 terkemuka dan juga mencampur urutan 1 byte dalam string 156 byte I sedang bermain dengan.
rafraf
2
Itu poin bagus tentang memimpin 0's. Saya tidak yakin saya percaya itu bisa mencampur urutan byte, dan akan sangat tertarik untuk melihatnya.
Dave L.
1
ya, segera setelah saya mengatakannya, saya juga tidak percaya :) Saya menjalankan perbandingan byte array dari BigInteger dengan mmyers'fromHexString dan (tanpa 0x00) terhadap string yang menyinggung - mereka identik. "Campuran" memang terjadi, tetapi mungkin itu sesuatu yang lain. Saya akan melihat lebih dekat besok
rafraf
3
Masalah dengan BigInteger adalah harus ada "tanda bit". Jika byte terkemuka memiliki bit set tinggi maka array byte yang dihasilkan memiliki 0 ekstra di posisi 1. Tapi tetap +1.
Gray
25

Satu baris:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

Bagi Anda yang tertarik pada kode aktual di belakang One-liners dari FractalizeR (saya membutuhkannya karena javax.xml.bind tidak tersedia untuk Android (secara default)), ini berasal dari com.sun.xml.internal.bind. DatatypeConverterImpl.java :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( char ch ) {
    if( '0'<=ch && ch<='9' )    return ch-'0';
    if( 'A'<=ch && ch<='F' )    return ch-'A'+10;
    if( 'a'<=ch && ch<='f' )    return ch-'a'+10;
    return -1;
}

private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}
Bert Regelink
sumber
3
DatatypeConverter juga tidak tersedia di Java 9 secara default. Yang berbahaya adalah kode yang menggunakannya akan dikompilasi di bawah Java 1.8 atau sebelumnya (Java 9 dengan pengaturan sumber ke sebelumnya), tetapi mendapatkan pengecualian runtime di bawah Java 9 tanpa "--add-modules java.se.ee".
Stephen M -pada mogok-
24

Ini HexBinaryAdaptermemberikan kemampuan untuk marshal dan unmarshal antara Stringdan byte[].

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

Itu hanya contoh yang saya ketikkan ... Saya sebenarnya hanya menggunakannya apa adanya dan tidak perlu membuat metode terpisah untuk menggunakannya.

GrkEngineer
sumber
5
Ini hanya berfungsi jika string input (hexString) memiliki jumlah karakter genap. Kalau tidak: Pengecualian di utas "utama" java.lang.IllegalArgumentException: hexBinary harus seimbang:
ovdsrn
3
Oh, terima kasih sudah menunjukkannya. Seorang pengguna seharusnya tidak memiliki jumlah ganjil karakter karena array byte direpresentasikan sebagai {0x00,0xA0,0xBf}. Setiap byte memiliki dua digit hex atau camilan. Jadi sejumlah byte harus selalu memiliki jumlah karakter genap. Terima kasih telah menyebutkan ini.
GrkEngineer
8
Anda dapat menggunakan java.xml.bind.DatatypeConverter.parseHexBinary (hexString) secara langsung alih-alih menggunakan HexBinaryAdapter (yang pada gilirannya memanggil DatatypeConverter). Dengan cara ini Anda tidak perlu membuat objek instance adaptor (karena metode DatatypeConverter statis).
Trevor Freeman
javax.xml.bind. * tidak lagi tersedia di Java 9. Yang berbahaya adalah kode yang menggunakannya akan dikompilasi di bawah Java 1.8 atau sebelumnya (Java 9 dengan pengaturan sumber sebelumnya), tetapi dapatkan pengecualian runtime berjalan di bawah Java 9.
Stephen M -on strike-
15

Berikut adalah metode yang benar-benar berfungsi (berdasarkan beberapa jawaban semi-benar sebelumnya):

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

Satu-satunya masalah yang mungkin saya lihat adalah jika string input sangat panjang; memanggil toCharArray () membuat salinan array internal string.

EDIT: Oh, dan omong-omong, byte ditandatangani di Java, jadi string input Anda dikonversi ke [0, -96, -65] alih-alih [0, 160, 191]. Tapi Anda mungkin sudah tahu itu.

Michael Myers
sumber
1
Terima kasih Michael - Anda seorang penyelamat! Bekerja pada proyek BlackBerry dan mencoba untuk mengubah representasi string dari byte kembali ke byte ... menggunakan metode "Byte.parseByte (byteString, 16)" RIM. Terus melempar NumberFormatExcpetion. Menghabiskan berjam-jam mencari tahu mengapa. Saran Anda tentang "Integer.praseInt ()" berhasil. Terima kasih lagi!!
BonanzaDriver
12

Di android, jika Anda bekerja dengan hex, Anda dapat mencoba okio .

penggunaan sederhana:

byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();

dan hasilnya akan

[-64, 0, 6, 0, 0]
Miao1007
sumber
Saya telah menguji berbagai metode tetapi yang ini setidaknya dua kali lebih cepat!
poby
5

The BigInteger()Metode dari java.math sangat lambat dan tidak recommandable.

Integer.parseInt(HEXString, 16)

dapat menyebabkan masalah dengan beberapa karakter tanpa mengonversi ke Digit / Integer

Metode yang Bekerja dengan Baik:

Integer.decode("0xXX") .byteValue()

Fungsi:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

Bersenang-senang, Semoga Sukses

Penembak jitu
sumber
4

EDIT: seperti yang ditunjukkan oleh @mmyers, metode ini tidak bekerja pada input yang berisi substring yang sesuai dengan byte dengan set bit tinggi ("80" - "FF"). Penjelasannya ada di Bug ID: 6259307 Byte.parseByte tidak berfungsi seperti yang diiklankan di Dokumentasi SDK .

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}
Blair Conrad
sumber
1
Tutup, tetapi metode ini gagal pada input yang diberikan "00A0BBF". Lihat bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 .
Michael Myers
1
Juga anehnya itu tidak berhubungan dengan "9C"
rafraf
1
@mmyers: whoa. Itu tidak baik. Maaf atas kebingunganmu. @ravigad: 9C memiliki masalah yang sama karena dalam hal ini bit tinggi diatur.
Blair Conrad
(byte) Short.parseShort (thisByte, 16) memecahkan masalah itu
Jamey Hicks
3

Untuk apa nilainya, inilah versi lain yang mendukung string panjang ganjil, tanpa menggunakan penggabungan string.

public static byte[] hexStringToByteArray(String input) {
    int len = input.length();

    if (len == 0) {
        return new byte[] {};
    }

    byte[] data;
    int startIdx;
    if (len % 2 != 0) {
        data = new byte[(len / 2) + 1];
        data[0] = (byte) Character.digit(input.charAt(0), 16);
        startIdx = 1;
    } else {
        data = new byte[len / 2];
        startIdx = 0;
    }

    for (int i = startIdx; i < len; i += 2) {
        data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
                + Character.digit(input.charAt(i+1), 16));
    }
    return data;
}
Conor Svensson
sumber
2

Saya selalu menggunakan metode seperti

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

metode ini membagi nilai hex yang dibatasi ruang tetapi tidak akan sulit untuk membuatnya membagi string pada kriteria lain seperti ke dalam pengelompokan dua karakter.

pfranza
sumber
Rangkaian string tidak perlu. Cukup gunakan Integer.valueOf (val, 16).
Michael Myers
Saya sudah mencoba menggunakan konversi radix seperti itu sebelumnya dan saya mendapatkan hasil yang beragam
pfranza
terima kasih - anehnya berfungsi dengan baik dengan string ini: "9C001C" atau "001C21" dan gagal dengan yang ini: "9C001C21" Pengecualian di utas "utama" java.lang.NumberFormatException: Untuk string input: "9C001C21" di java.lang. NumberFormatException.forInputString (Sumber Tidak Diketahui)
rafraf
(Itu tidak lebih aneh daripada dalam Byte/ bytekasus: bit tertinggi ditetapkan tanpa memimpin -)
greybeard
2

Saya suka solusi Character.digit, tapi inilah cara saya menyelesaikannya

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}
Panik Kernel
sumber
2

Kode yang disajikan oleh Bert Regelink tidak berfungsi. Coba yang berikut ini:

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class Test
{  
    @Test
    public void testObjectStreams( ) throws IOException, ClassNotFoundException
    {     
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);

            String stringTest = "TEST";
            oos.writeObject( stringTest );

            oos.close();
            baos.close();

            byte[] bytes = baos.toByteArray();
            String hexString = DatatypeConverter.printHexBinary( bytes);
            byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);

            assertArrayEquals( bytes, reconvertedBytes );

            ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);

            String readString = (String) ois.readObject();

            assertEquals( stringTest, readString);
        }
    }
Sean Coffey
sumber
2
Ini benar-benar masalah yang berbeda, dan mungkin berada di utas lainnya.
Sean Coffey
1

Saya menemukan Kernel Panic memiliki solusi yang paling berguna bagi saya, tetapi mengalami masalah jika string hex adalah angka ganjil. dipecahkan dengan cara ini:

boolean isOdd(int value)
{
    return (value & 0x01) !=0;
}

private int hexToByte(byte[] out, int value)
{
    String hexVal = "0123456789ABCDEF"; 
    String hexValL = "0123456789abcdef";
    String st = Integer.toHexString(value);
    int len = st.length();
    if (isOdd(len))
        {
        len+=1; // need length to be an even number.
        st = ("0" + st);  // make it an even number of chars
        }
    out[0]=(byte)(len/2);
    for (int i =0;i<len;i+=2)
    {
        int hh = hexVal.indexOf(st.charAt(i));
            if (hh == -1)  hh = hexValL.indexOf(st.charAt(i));
        int lh = hexVal.indexOf(st.charAt(i+1));
            if (lh == -1)  lh = hexValL.indexOf(st.charAt(i+1));
        out[(i/2)+1] = (byte)((hh << 4)|lh);
    }
    return (len/2)+1;
}

Saya menambahkan sejumlah nomor hex ke array, jadi saya meneruskan referensi ke array yang saya gunakan, dan int saya perlu dikonversi dan mengembalikan posisi relatif nomor hex berikutnya. Jadi array byte terakhir memiliki [0] jumlah pasangan hex, [1 ...] pasangan hex, kemudian jumlah pasangan ...

Clayton Balabanov
sumber
1

Berdasarkan solusi pilihan, berikut ini harus sedikit lebih efisien:

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

Karena: konversi awal ke array arang memberikan pemeriksaan panjang di charAt

Philip Helger
sumber
1

Jika Anda memiliki preferensi untuk Java 8 stream sebagai gaya pengkodean Anda maka ini dapat dicapai hanya dengan menggunakan JDK primitif.

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

The , 0, s2.size()parameter dalam fungsi kolektor concatenate dapat dihilangkan jika Anda tidak keberatan penangkapan IOException.

Andy Brown
sumber
0
public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}
David V
sumber
0

Solusi formal saya:

/**
 * Decodes a hexadecimally encoded binary string.
 * <p>
 * Note that this function does <em>NOT</em> convert a hexadecimal number to a
 * binary number.
 *
 * @param hex Hexadecimal representation of data.
 * @return The byte[] representation of the given data.
 * @throws NumberFormatException If the hexadecimal input string is of odd
 * length or invalid hexadecimal string.
 */
public static byte[] hex2bin(String hex) throws NumberFormatException {
    if (hex.length() % 2 > 0) {
        throw new NumberFormatException("Hexadecimal input string must have an even length.");
    }
    byte[] r = new byte[hex.length() / 2];
    for (int i = hex.length(); i > 0;) {
        r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
    }
    return r;
}

private static int digit(char ch) {
    int r = Character.digit(ch, 16);
    if (r < 0) {
        throw new NumberFormatException("Invalid hexadecimal string: " + ch);
    }
    return r;
}

Seperti fungsi PHP hex2bin () tetapi dalam gaya Java.

Contoh:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
Daniel De León
sumber
0

Terlambat ke pesta, tetapi saya telah menggabungkan jawaban di atas oleh DaveL ke dalam kelas dengan tindakan sebaliknya - kalau-kalau itu membantu.

public final class HexString {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    private HexString() {}

    public static final String fromBytes(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
            buf.append(HexString.digits[bytes[i] & 0x0f]);
        }
        return buf.toString();
    }

    public static final byte[] toByteArray(final String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("Input string must contain an even number of characters");
        }
        final int len = hexString.length();
        final byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}

Dan kelas uji JUnit:

public class TestHexString {

    @Test
    public void test() {
        String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};

        for (int i = 0; i < tests.length; i++) {
            String in = tests[i];
            byte[] bytes = HexString.toByteArray(in);
            String out = HexString.fromBytes(bytes);
            System.out.println(in); //DEBUG
            System.out.println(out); //DEBUG
            Assert.assertEquals(in, out);

        }

    }

}
DrPhill
sumber
0

Saya tahu ini adalah utas yang sangat lama, tetapi masih ingin menambahkan nilai sen saya.

Jika saya benar-benar perlu kode hex string sederhana ke konverter biner, saya ingin melakukannya sebagai berikut.

public static byte[] hexToBinary(String s){

  /*
   * skipped any input validation code
   */

  byte[] data = new byte[s.length()/2];

  for( int i=0, j=0; 
       i<s.length() && j<data.length; 
       i+=2, j++)
  {
     data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
  }

  return data;
}
harimau
sumber
0

Sejauh ini bukan solusi terbersih. Tapi itu bekerja untuk saya dan diformat dengan baik:

private String createHexDump(byte[] msg, String description) {
    System.out.println();
    String result = "\n" + description;
    int currentIndex = 0;
    int printedIndex = 0;
    for(int i=0 ; i<msg.length ; i++){
        currentIndex++;
        if(i == 0){
            result += String.format("\n  %04x ", i);
        }
        if(i % 16 == 0 && i != 0){
            result += " | ";
            for(int j=(i-16) ; j<msg.length && j<i ; j++) {
                char characterToAdd = (char) msg[j];
                if (characterToAdd == '\n') {
                    characterToAdd = ' ';
                }
                result += characterToAdd;
                printedIndex++;
            }

            result += String.format("\n  %04x ", i);
        }

        result += String.format("%02x ", msg[i]);
    }

    if(currentIndex - printedIndex > 0){
        int leftOvers = currentIndex - printedIndex;
        for(int i=0 ; i<16-leftOvers ; i++){
            result += "   ";
        }

        result += " | ";

        for(int i=msg.length-leftOvers ; i<msg.length ; i++){
            char characterToAdd = (char) msg[i];
            if (characterToAdd == '\n') {
                characterToAdd = ' ';
            }
            result += characterToAdd;
        }
    }

    result += "\n";

    return result;
}

Hasil:

  S -> C
    0000 0b 00 2e 06 4d 6f 72 69 74 7a 53 6f 6d 65 20 54  |  .Heyyy Some T
    0010 43 50 20 73 74 75 66 66 20 49 20 63 61 70 74 75  | CP stuff I captu
    0020 72 65 64 2e 2e 77 65 6c 6c 20 66 6f 72 6d 61 74  | red..well format
    0030 3f                                               | ?
Moritz Schmidt
sumber
-2

Saya pikir akan melakukannya untuk Anda. Saya menggabungkannya dari fungsi serupa yang mengembalikan data sebagai string:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}
Bob King
sumber
Pertama, Anda tidak perlu mengubah string menjadi huruf besar. Kedua, dimungkinkan untuk menambahkan karakter langsung ke StringBuffer, yang seharusnya jauh lebih efisien.
Michael Myers
-2

Bagi saya ini solusinya, HEX = "FF01" lalu bagi menjadi FF (255) dan 01 (01)

private static byte[] BytesEncode(String encoded) {
    //System.out.println(encoded.length());
    byte result[] = new byte[encoded.length() / 2];
    char enc[] = encoded.toUpperCase().toCharArray();
    String curr = "";
    for (int i = 0; i < encoded.length(); i=i+2) {
        curr = encoded.substring(i,i+2);
        System.out.println(curr);
        if(i==0){
            result[i]=((byte) Integer.parseInt(curr, 16));
        }else{
            result[i/2]=((byte) Integer.parseInt(curr, 16));
        }

    }
    return result;
}
Alejandro
sumber
Pertanyaan ini telah dijawab untuk sementara waktu dan memiliki beberapa alternatif bagus; Sayangnya, jawaban Anda tidak memberikan nilai yang meningkat secara signifikan pada saat ini.
rfornal