Bagaimana cara mengubah array byte ke string hex di Jawa?

649

Saya memiliki byte array yang diisi dengan angka hex dan mencetaknya dengan cara mudah cukup sia-sia karena ada banyak elemen yang tidak patut dicetak. Yang saya butuhkan adalah hexcode yang tepat dalam bentuk:3a5f771c

Andre
sumber
12
Mengapa tidak mencobanya saja dan tunjukkan apa yang Anda punya. Anda tidak akan rugi apa pun dan semua untuk mendapat keuntungan. Integer memiliki toHexString(...)metode yang dapat membantu jika ini yang Anda cari. Juga String.format(...)dapat melakukan beberapa trik format rapi menggunakan %2xstring kode.
Hovercraft Full Of Belut
"Yang saya butuhkan adalah hexcode yang tepat dalam bentuk: 3a5f771c ..." - Anda meminta formulir yang tepat, tetapi Anda tidak memberikan contoh yang tepat. Pergi pada apa yang Anda berikan, konversi empat byte pertama menjadi sebuah string, kemudian gabungkan elips ke string.
jww
1
Dengan bantuan stream di Java 8, ini dapat dengan mudah diimplementasikan sebagai: byte String statisArrayToHex (byte [] a) {return IntStream.range (0, a.length) .mapToObj (i -> String.format ("% 02x ", a [i])) .reduce ((acc, v) -> acc +" "+ v) .get (); }
tibetty

Jawaban:

901

Dari diskusi di sini , dan terutama ini jawabannya, ini adalah fungsi saya gunakan saat ini:

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}

Tolok ukur kecil saya sendiri (satu juta byte seribu kali, 256 byte 10 juta kali) menunjukkannya jauh lebih cepat daripada alternatif lain, sekitar separuh waktu pada array panjang. Dibandingkan dengan jawaban yang saya ambil, beralih ke op bitwise --- seperti yang disarankan dalam diskusi --- memotong sekitar 20% dari waktu untuk array panjang. (Sunting: Ketika saya mengatakan itu lebih cepat daripada alternatif, maksud saya kode alternatif yang ditawarkan dalam diskusi. Kinerja setara dengan Commons Codec, yang menggunakan kode yang sangat mirip.)

Versi 2k20, sehubungan dengan Java 9 string kompak:

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}
mungkinKita dapatMenghasilkanAV
sumber
266
Saya baru saja menemukan javax.xml.bind.DataTypeConverter , bagian dari distribusi standar. Mengapa ini tidak muncul ketika Anda Google masalah seperti ini? Banyak alat yang bermanfaat, termasuk String printHexBinary(byte[])dan byte[] parseHexBinary(String). printHexBinaryNamun, jauh lebih lambat (2x) dari fungsi dalam jawaban ini. (Saya memeriksa sumbernya; ia menggunakan stringBuilder. parseHexBinaryMenggunakan array.) Sungguh, untuk sebagian besar tujuan itu cukup cepat dan Anda mungkin sudah memilikinya.
mungkinKita dapat melakukannya
75
+1 untuk jawaban karena Android tidak memiliki DataTypeConverter
Vaiden
7
@maybeWeCouldStealAVan: JDK 7 sekarang open source. Kita harus mengirimkan tambalan untuk meningkatkan kinerja printHexBinary?
kevinarpe
3
@mungkinbeWeCouldStealAVan bisa tolong jelaskan cara kerjanya. Saya mengikuti sebagian besar tetapi sangat suka memahami apa yang terjadi ketika menggunakan kode. Terima kasih!
jjNford
24
javax.xml.bind.DataTypeConvertersedang dihapus dari Jawa 11.
The Impaler
421

The Apache Commons Codec perpustakaan memiliki Hex kelas untuk melakukan hal ini jenis pekerjaan.

import org.apache.commons.codec.binary.Hex;

String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
chooban
sumber
12
@cytinus - Downvote saya terjadi 4 bulan yang lalu jadi saya tidak sepenuhnya yakin apa yang saya pikirkan, tapi saya mungkin keberatan dengan ukuran perpustakaan. Ini adalah fungsi kecil dalam program; tidak perlu menambahkan perpustakaan besar seperti itu ke proyek untuk melakukannya.
ArtOfWarfare
6
@ ArtOfWarefare Saya setuju, jadi alih-alih import org.apache.commons.codec.*;Anda bisa melakukannyaimport org.apache.commons.codec.binary.Hex;
cytinus
12
@ ArtOfWarfare saya harus tidak setuju. Satu-satunya hal yang mengerikan adalah bahwa perpustakaan apache commons tidak disertakan secara default dengan JRE dan JDK. Ada beberapa perpustakaan yang sangat berguna sehingga mereka seharusnya berada di jalur kelas Anda secara default, dan ini adalah salah satunya.
corsiKa
29
Saya sangat merekomendasikan jawaban ini ditukar sebagai jawaban teratas. Pilih selalu untuk menggunakan pustaka sumber terbuka yang teruji baik, berkinerja, dan lebih dari kode kustom yang tidak membaik.
Dmitriy Likhten
6
Atau jika Anda menggunakan BouncyCastle ( org.bouncycastle: bcprov-jdk15on ), Anda dapat menggunakan kelas org.bouncycastle.util.encoders.Hexini String toHexString(byte[] data)
:,
320

Metode javax.xml.bind.DatatypeConverter.printHexBinary(), bagian dari Arsitektur Java untuk XML Binding (JAXB) , adalah cara yang mudah untuk mengkonversi byte[]ke string hex. The DatatypeConverterkelas juga termasuk banyak metode manipulasi data lainnya yang berguna.

Di Java 8 dan sebelumnya, JAXB adalah bagian dari perpustakaan standar Java. Itu ditinggalkan dengan Java 9 dan dihapus dengan Java 11 , sebagai bagian dari upaya untuk memindahkan semua paket Java EE ke perpustakaan mereka sendiri. Ceritanya panjang . Sekarang, javax.xml.bindtidak ada, dan jika Anda ingin menggunakan JAXB, yang berisi DatatypeConverter, Anda harus menginstal JAXB API dan JAXB Runtime dari Maven.

Contoh penggunaan:

byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);

Akan menghasilkan:

000086003D

Jawaban ini sama dengan yang ini .

PhoneixS
sumber
13
Solusi yang bagus, meskipun sayangnya tidak satu yang valid di Android.
Kazriko
@Kazriko mungkin Anda ingin membaca code.google.com/p/dalvik/wiki/JavaxPackages . Ini adalah cara untuk mendapatkan kelas javax ke Android. Tetapi jika Anda hanya ingin mengkonversi ke hex, itu tidak sepadan dengan masalahnya.
PhoneixS
13
DatatypeConverter tidak lagi dapat diakses pada JDK 9
pmcollins
3
@PhoneixS Masih ada, tetapi bukan bagian dari runtime default (karena modul Java 9).
Spotlight
2
jangan mengandalkan javax.xml.bind, ia mengkompilasi dengan baik tetapi tidak dapat ditemukan saat runtime. jika Anda melakukannya, bersiaplah untuk menangani java.lang.NoClassDefFoundError
Dmitry
227

Solusi paling sederhana, tidak ada lib eksternal, tanpa konstanta digit:

public static String byteArrayToHex(byte[] a) {
   StringBuilder sb = new StringBuilder(a.length * 2);
   for(byte b: a)
      sb.append(String.format("%02x", b));
   return sb.toString();
}
Pointer Null
sumber
14
Ini sangat lambat, rata-rata 1000 kali lebih lambat (untuk 162 byte panjang) daripada yang ada di respons teratas. Hindari menggunakan String.Format jika masalah kinerja.
pt123
8
Mungkin lambat. Ini bagus untuk hal-hal yang terjadi sesekali, seperti login atau sejenisnya.
Pointer Null
29
Jika lambat, lalu bagaimana? Dalam kasus penggunaan saya ini hanya untuk pernyataan debug, jadi terima kasih untuk fragmen kode ini.
vikingsteve
8
Menggunakan kembali perpustakaan dengan memasukkan file JAR ekstra beberapa lusin kB tidak akan efisien jika semua yang Anda butuhkan adalah fungsi ini (pada beberapa platform seperti Android, seluruh Jar dimasukkan dalam aplikasi akhir). Dan terkadang kode yang lebih pendek dan lebih jelas lebih baik ketika kinerja tidak diperlukan.
personne3000
2
@ personne3000 mungkin, tetapi dalam hal ini Anda memerlukan dukungan streaming, bukan fitur panggilan tunggal. yang ini mudah dimengerti dan diingat, dan karenanya harus dipertahankan.
Maarten Bodewes
59

Solusi Jambu Biji, untuk kelengkapan:

import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);

Sekarang hexadalah "48656c6c6f20776f726c64".

Stephan202
sumber
Dalam Jambu Biji Anda juga bisa menggunakan new HashCode(bytes).toString().
mfulton26
1
Pada Guava 22.0 ituHashCode.fromBytes(checksum).toString()
Devstr
43

Oneliner sederhana ini berfungsi untuk saya
String result = new BigInteger(1, inputBytes).toString(16);
EDIT - Menggunakan ini akan menghapus angka nol di depan, tapi hei berfungsi untuk kasus penggunaan saya. Terima kasih @Voicu untuk menunjukkannya

everconfusedGuy
sumber
56
Oneliner ini menurun hingga nol byte.
Voicu
@Voicu ... Dan itu akan menambah nol memimpin 50% dari waktu.
Maarten Bodewes
27

Berikut adalah beberapa opsi umum yang dipesan dari sederhana (satu-liner) ke kompleks (perpustakaan besar). Jika Anda tertarik dengan kinerja, lihat tolok ukur mikro di bawah ini.

Opsi 1: Cuplikan kode - Sederhana

Satu solusi yang sangat sederhana adalah dengan menggunakan BigIntegerrepresentasi hex 's:

new BigInteger(1, someByteArray).toString(16)

Perhatikan bahwa karena ini menangani angka - angka yang bukan byte-string, ini akan menghilangkan angka nol di depan - ini mungkin atau mungkin bukan yang Anda inginkan (mis. 000AE3Vs 0AE3untuk input 3 byte). Ini juga sangat lambat, sekitar 100x lebih lambat dibandingkan dengan opsi berikutnya.

Opsi 2: Potongan kode - Lanjutan

Berikut ini adalah cuplikan kode fitur lengkap, salin & tempel yang mendukung huruf besar / kecil dan endianness . Ini dioptimalkan untuk meminimalkan kompleksitas memori dan memaksimalkan kinerja dan harus kompatibel dengan semua versi Java modern (5+).

private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};

public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {

    // our output size will be exactly 2x byte-array length
    final char[] buffer = new char[byteArray.length * 2];

    // choose lower or uppercase lookup table
    final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;

    int index;
    for (int i = 0; i < byteArray.length; i++) {
        // for little endian we count from last to first
        index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;

        // extract the upper 4 bit and look up char (0-A)
        buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
        // extract the lower 4 bit and look up char (0-A)
        buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
    }
    return new String(buffer);
}

public static String encode(byte[] byteArray) {
    return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}

Kode sumber lengkap dengan lisensi dan dekoder Apache v2 dapat ditemukan di sini .

Opsi 3: Menggunakan perpustakaan kecil yang dioptimalkan: bytes-java

Saat mengerjakan proyek saya sebelumnya, saya membuat toolkit kecil ini untuk bekerja dengan byte di Jawa. Tidak memiliki dependensi eksternal dan kompatibel dengan Java 7+. Ini termasuk, antara lain, HEX yang sangat cepat dan teruji en / decoder:

import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()

Anda dapat memeriksanya di Github: bytes-java .

Opsi 4: Apache Commons Codec

Tentu saja ada codec commons baik . ( Peringatan peringatan di depan ) Saat mengerjakan proyek yang diuraikan di atas saya menganalisis kode dan cukup kecewa; banyak duplikat kode yang tidak terorganisir, kodek usang dan eksotis mungkin hanya berguna untuk sangat sedikit dan sangat direkayasa dan lambat implementasi codec populer (khususnya Base64). Karena itu saya akan membuat keputusan berdasarkan informasi jika Anda ingin menggunakannya atau alternatif. Bagaimanapun, jika Anda masih ingin menggunakannya, berikut ini adalah cuplikan kode:

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));

Opsi 5: Google Guava

Lebih sering daripada tidak Anda sudah memiliki jambu biji sebagai ketergantungan. Jika demikian gunakan saja:

import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);

Opsi 6: Keamanan Musim Semi

Jika Anda menggunakan kerangka kerja Spring dengan Keamanan Spring Anda dapat menggunakan yang berikut ini:

import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));

Opsi 7: Bouncy Castle

Jika Anda sudah menggunakan kerangka keamanan Bouncy Castle Anda dapat menggunakan Hexutilnya:

import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);

Not Really Option 8: Java 9+ Kompatibilitas atau 'Jangan Gunakan JAXBs javax / xml / bind / DatatypeConverter'

Dalam versi Java sebelumnya (8 dan di bawah) kode Java untuk JAXB dimasukkan sebagai ketergantungan runtime. Karena modularisasi Java 9 dan Jigsaw kode Anda tidak dapat mengakses kode lain di luar modul itu tanpa deklarasi eksplisit. Jadi waspadai jika Anda mendapatkan pengecualian seperti:

java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

saat berjalan pada JVM dengan Java 9+. Jika demikian maka alihkan implementasi ke salah satu alternatif di atas. Lihat juga pertanyaan ini .


Tolok Ukur Mikro

Berikut ini adalah hasil dari array byte encoding byte benchmark JMH mikro sederhana dari ukuran yang berbeda . Nilainya adalah operasi per detik, jadi lebih tinggi lebih baik. Perhatikan bahwa tolok ukur mikro sangat sering tidak mewakili perilaku dunia nyata, jadi ambil hasil ini dengan sebutir garam.

| Name (ops/s)         |    16 byte |    32 byte |  128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger     |  2,088,514 |  1,008,357 |   133,665 |       4 |
| Opt2/3: Bytes Lib    | 20,423,170 | 16,049,841 | 6,685,522 |     825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 |     529 |
| Opt5: Guava          | 10,177,925 |  6,937,833 | 2,094,658 |     257 |
| Opt6: Spring         | 18,704,986 | 13,643,374 | 4,904,805 |     601 |
| Opt7: BC             |  7,501,666 |  3,674,422 | 1,077,236 |     152 |
| Opt8: JAX-B          | 13,497,736 |  8,312,834 | 2,590,940 |     346 |

Spesifikasi: JDK 8u202, i7-7700K, Win10, 24GB Ram. Lihat patokan lengkap di sini .

Patrick Favre
sumber
25

Gunakan kelas DataTypeConverterjavax.xml.bind.DataTypeConverter

String hexString = DatatypeConverter.printHexBinary(bytes[] raw);

Karang
sumber
2
Kelas dihapus di Jawa 11. Lihat: JEP 320: Hapus Java EE dan Modul CORBA
Basil Bourque
21

Saya akan menggunakan sesuatu seperti ini untuk panjang tetap, seperti hash:

md5sum = String.format("%032x", new BigInteger(1, md.digest()));
Usagi Miyamoto
sumber
2
Terima kasih, ini sangat rapi dan sesuai.
Deepan Prabhu Babu
18

Saya menemukan tiga cara berbeda di sini: http://www.rgagnon.com/javadetails/java-0596.html

Yang paling elegan, seperti yang juga dicatat, menurut saya adalah yang ini:

static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
    if ( raw == null ) {
        return null;
    }
    final StringBuilder hex = new StringBuilder( 2 * raw.length );
    for ( final byte b : raw ) {
        hex.append(HEXES.charAt((b & 0xF0) >> 4))
            .append(HEXES.charAt((b & 0x0F)));
    }
    return hex.toString();
}
Michael Bisbjerg
sumber
Metode lain berjalan pada sampel 64 byte saya dalam 5ms, yang ini berjalan dalam 0ms. Mungkin yang terbaik karena tidak ada fungsi String lainnya seperti format.
Joseph Lust
if (raw == null) return nulltidak gagal dengan cepat. Mengapa Anda pernah menggunakan nullkunci?
Maarten Bodewes
Saya kira itu kebiasaan untuk memasukkan validasi. Dalam hal ini, kami mencegah pengecualian referensi Null, dan menyerahkannya kepada pemanggil untuk menangani data yang buruk.
Michael Bisbjerg
16

Dengan biaya kecil menyimpan tabel pencarian implementasi ini sederhana dan sangat cepat.

 private static final char[] BYTE2HEX=(
    "000102030405060708090A0B0C0D0E0F"+
    "101112131415161718191A1B1C1D1E1F"+
    "202122232425262728292A2B2C2D2E2F"+
    "303132333435363738393A3B3C3D3E3F"+
    "404142434445464748494A4B4C4D4E4F"+
    "505152535455565758595A5B5C5D5E5F"+
    "606162636465666768696A6B6C6D6E6F"+
    "707172737475767778797A7B7C7D7E7F"+
    "808182838485868788898A8B8C8D8E8F"+
    "909192939495969798999A9B9C9D9E9F"+
    "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+
    "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+
    "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
    "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+
    "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+
    "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray();
   ; 

  public static String getHexString(byte[] bytes) {
    final int len=bytes.length;
    final char[] chars=new char[len<<1];
    int hexIndex;
    int idx=0;
    int ofs=0;
    while (ofs<len) {
      hexIndex=(bytes[ofs++] & 0xFF)<<1;
      chars[idx++]=BYTE2HEX[hexIndex++];
      chars[idx++]=BYTE2HEX[hexIndex];
    }
    return new String(chars);
  }
higginse
sumber
6
Mengapa tidak menginisialisasi BYTE2HEXarray dengan forsiklus sederhana ?
icza
@icza Apakah itu mungkin dengan bidang final statis (alias konstan)?
nevelis
1
@nevelis Dapat ditugaskan dalam satu static { }blok.
マ ル ち ゃ ん だ よ
1
@icza karena lebih cepat untuk meng-hardcode tabel pencarian daripada membuatnya. Di sini kompleksitas memori diperdagangkan dengan kompleksitas waktu, yaitu. membutuhkan lebih banyak memori tetapi lebih cepat (setiap sedikit di kedua ujungnya)
Patrick Favre
8

Bagaimana dengan ini?

    String byteToHex(final byte[] hash)
    {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
Manan Bakshi
sumber
3

Kita tidak perlu menggunakan pustaka eksternal atau menulis kode berdasarkan loop dan konstanta.
Cukup ini saja:

byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);
Marian
sumber
1
Ini sangat mirip dengan Jawaban everconfusedGuy.
Scratte
2

Saya lebih suka menggunakan ini:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes, int offset, int count) {
    char[] hexChars = new char[count * 2];
    for ( int j = 0; j < count; j++ ) {
        int v = bytes[j+offset] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

Ini sedikit lebih fleksibel dari jawaban yang diterima. Secara pribadi, saya menyimpan jawaban yang diterima dan kelebihan ini, dapat digunakan dalam lebih banyak konteks.

Bamaco
sumber
Pertanyaan aslinya adalah byte [] ke String. Lihat hex to bytes [] atau ajukan pertanyaan lain, @NonExistent.
Bamaco
2

Saya biasanya menggunakan metode berikut untuk pernyataan debuf, tetapi saya tidak tahu apakah itu cara terbaik untuk melakukannya atau tidak

private static String digits = "0123456789abcdef";

public static String toHex(byte[] data){
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i != data.length; i++)
    {
        int v = data[i] & 0xff;
        buf.append(digits.charAt(v >> 4));
        buf.append(digits.charAt(v & 0xf));
    }
    return buf.toString();
}
Snox
sumber
2
Jika debuffer Anda memiliki hari yang buruk, cobalah cluing StringBuilder Instansiasi dengan sejumlah karakter dukungan: StringBuilder buf = new StringBuilder(data.length * 2);.
greybeard
2

Ok jadi ada banyak cara untuk melakukan ini, tetapi jika Anda memutuskan untuk menggunakan perpustakaan saya akan menyarankan mencari-cari di proyek Anda untuk melihat apakah ada sesuatu yang telah dilaksanakan di perpustakaan yang sudah menjadi bagian dari proyek Anda sebelum menambahkan perpustakaan baru hanya untuk melakukan ini. Misalnya jika Anda belum memilikinya

org.apache.commons.codec.binary.Hex

mungkin kamu memang punya ...

org.apache.xerces.impl.dv.util.HexBin

Aaron Cooley
sumber
2

Jika Anda menggunakan kerangka kerja Spring Security, Anda dapat menggunakan:

import org.springframework.security.crypto.codec.Hex

final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));
java-addict301
sumber
2

Menambahkan toples utilitas untuk fungsi sederhana bukanlah pilihan yang baik. Alih-alih merakit kelas utilitas Anda sendiri. berikut ini mungkin implementasi lebih cepat.

public class ByteHex {

    public static int hexToByte(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 String[] byteToHexTable = new String[]
    {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
        "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
        "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
        "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
        "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
    };

    private static final String[] byteToHexTableLowerCase = new String[]
    {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
        "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
        "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
        "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
        "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
        "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"
    };

    public static String byteToHex(byte b){
        return byteToHexTable[b & 0xFF];
    }

    public static String byteToHex(byte[] bytes){
        if(bytes == null) return null;
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
        return sb.toString();
    }

    public static String byteToHex(short[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
        return sb.toString();
    }

    public static String byteToHexLowerCase(byte[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
        return sb.toString();
    }

    public static byte[] hexToByte(String hexString) {
        if(hexString == null) return null;
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
        }
        return byteArray;
    }

    public static byte hexPairToByte(char ch1, char ch2) {
        return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
    }


}
krishna Telgave
sumber
1

Varian kecil dari solusi yang diajukan oleh @maybewecouldstealavan, yang memungkinkan Anda secara visual menggabungkan N byte bersama-sama dalam string hex output:

 final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
 final static char BUNDLE_SEP = ' ';

public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) {
        char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)];
        for (int j = 0, k = 1; j < bytes.length; j++, k++) {
                int v = bytes[j] & 0xFF;
                int start = (j * 2) + j/bundleSize;

                hexChars[start] = HEX_ARRAY[v >>> 4];
                hexChars[start + 1] = HEX_ARRAY[v & 0x0F];

                if ((k % bundleSize) == 0) {
                        hexChars[start + 2] = BUNDLE_SEP;
                }   
        }   
        return new String(hexChars).trim();    
}

Itu adalah:

bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E

bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E
Campa
sumber
1

Tidak dapat menemukan solusi pada halaman ini yang tidak

  1. Gunakan satu lingkaran
  2. Gunakan javax.xml.bind.DatatypeConverter yang mengkompilasi dengan baik tetapi sering melempar java.lang.NoClassDefFoundError saat runtime.

Inilah solusi yang tidak memiliki kekurangan di atas (tidak ada janji saya tidak memiliki kekurangan lain sekalipun)

import java.math.BigInteger;

import static java.lang.System.out;
public final class App2 {
    // | proposed solution.
    public static String encode(byte[] bytes) {          
        final int length = bytes.length;

        // | BigInteger constructor throws if it is given an empty array.
        if (length == 0) {
            return "00";
        }

        final int evenLength = (int)(2 * Math.ceil(length / 2.0));
        final String format = "%0" + evenLength + "x";         
        final String result = String.format (format, new BigInteger(bytes));

        return result;
    }

    public static void main(String[] args) throws Exception {
        // 00
        out.println(encode(new byte[] {})); 

        // 01
        out.println(encode(new byte[] {1})); 

        //203040
        out.println(encode(new byte[] {0x20, 0x30, 0x40})); 

        // 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
        out.println(encode("All your base are belong to us.".getBytes()));
    }
}   

Saya tidak bisa mendapatkan ini di bawah 62 opcodes, tetapi jika Anda dapat hidup tanpa 0 padding seandainya byte pertama kurang dari 0x10, maka solusi berikut ini hanya menggunakan 23 opcodes. Benar-benar menunjukkan bagaimana solusi "mudah diimplementasikan sendiri" seperti "pad dengan nol jika panjang string aneh" bisa menjadi cukup mahal jika implementasi asli belum tersedia (atau dalam hal ini, jika BigInteger memiliki opsi untuk awalan dengan nol di toString).

public static String encode(byte[] bytes) {          
    final int length = bytes.length;

    // | BigInteger constructor throws if it is given an empty array.
    if (length == 0) {
        return "00";
    }

    return new BigInteger(bytes).toString(16);
}
Dmitry
sumber
1

Solusi saya didasarkan pada solusi maybeWeCouldStealAVan, tetapi tidak bergantung pada tabel pencarian tambahan yang dialokasikan. Itu tidak menggunakan hacks 'int-to-char' (sebenarnya Character.forDigit(), melakukan beberapa perbandingan untuk memeriksa apa digit sebenarnya) dan dengan demikian mungkin sedikit lebih lambat. Silakan menggunakannya kapan pun Anda mau. Bersulang.

public static String bytesToHex(final byte[] bytes)
{
    final int numBytes = bytes.length;
    final char[] container = new char[numBytes * 2];

    for (int i = 0; i < numBytes; i++)
    {
        final int b = bytes[i] & 0xFF;

        container[i * 2] = Character.forDigit(b >>> 4, 0x10);
        container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
    }

    return new String(container);
}
Netherwire
sumber
0

// Menggeser byte lebih efisien // Anda dapat menggunakan ini juga

public static String getHexString (String s) 
{
    byte[] buf = s.getBytes();

    StringBuffer sb = new StringBuffer();

    for (byte b:buf)
    {
        sb.append(String.format("%x", b));
    }


        return sb.toString();
}
BluePurse
sumber
0

Jika Anda mencari array byte persis seperti ini untuk python, saya telah mengubah implementasi Java ini menjadi python.

class ByteArray:

@classmethod
def char(cls, args=[]):
    cls.hexArray = "0123456789ABCDEF".encode('utf-16')
    j = 0
    length = (cls.hexArray)

    if j < length:
        v = j & 0xFF
        hexChars = [None, None]
        hexChars[j * 2] = str( cls.hexArray) + str(v)
        hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F)
        # Use if you want...
        #hexChars.pop()

    return str(hexChars)

array = ByteArray()
print array.char(args=[])
SkippsDev
sumber
0
  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;
  } 
田 咖啡
sumber
0

Berikut ini adalah java.util.Base64implementasi seperti (sebagian), bukan?

public class Base16/*a.k.a. Hex*/ {
    public static class Encoder{
        private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        private boolean upper;
        public Encoder(boolean upper) {
            this.upper=upper;
        }
        public String encode(byte[] data){
            char[] value=new char[data.length*2];
            char[] toHex=upper?toUpperHex:toLowerHex;
            for(int i=0,j=0;i<data.length;i++){
                int octet=data[i]&0xFF;
                value[j++]=toHex[octet>>4];
                value[j++]=toHex[octet&0xF];
            }
            return new String(value);
        }
        static final Encoder LOWER=new Encoder(false);
        static final Encoder UPPER=new Encoder(true);
    }
    public static Encoder getEncoder(){
        return Encoder.LOWER;
    }
    public static Encoder getUpperEncoder(){
        return Encoder.UPPER;
    }
    //...
}
fuweichin
sumber
0
private static String bytesToHexString(byte[] bytes, int length) {
        if (bytes == null || length == 0) return null;

        StringBuilder ret = new StringBuilder(2*length);

        for (int i = 0 ; i < length ; i++) {
            int b;

            b = 0x0f & (bytes[i] >> 4);
            ret.append("0123456789abcdef".charAt(b));

            b = 0x0f & bytes[i];
            ret.append("0123456789abcdef".charAt(b));
        }

        return ret.toString();
    }
kakopappa
sumber
0
Converts bytes data to hex characters

@param bytes byte array to be converted to hex string
@return byte String in hex format

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}
Rajneesh Shukla
sumber