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
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.
"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:
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:
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 ));
@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)
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.
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:
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.
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
@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:
newBigInteger(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+).
privatestaticfinalchar[] LOOKUP_TABLE_LOWER =newchar[]{0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x61,0x62,0x63,0x64,0x65,0x66};privatestaticfinalchar[] LOOKUP_TABLE_UPPER =newchar[]{0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x41,0x42,0x43,0x44,0x45,0x46};publicstaticString encode(byte[] byteArray,boolean upperCase,ByteOrder byteOrder){// our output size will be exactly 2x byte-array lengthfinalchar[] buffer =newchar[byteArray.length *2];// choose lower or uppercase lookup tablefinalchar[] 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)];}returnnewString(buffer);}publicstaticString 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:
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:
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:
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)|16byte|32byte|128byte|0.95 MB ||----------------------|-----------:|-----------:|----------:|--------:||Opt1:BigInteger|2,088,514|1,008,357|133,665|4||Opt2/3:BytesLib|20,423,170|16,049,841|6,685,522|825||Opt4:ApacheCommons|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|
Yang paling elegan, seperti yang juga dicatat, menurut saya adalah yang ini:
staticfinalString HEXES ="0123456789ABCDEF";publicstaticString getHex(byte[] raw ){if( raw ==null){returnnull;}finalStringBuilder hex =newStringBuilder(2* raw.length );for(finalbyte b : raw ){
hex.append(HEXES.charAt((b &0xF0)>>4)).append(HEXES.charAt((b &0x0F)));}return hex.toString();}
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.
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(finalbyte[] hash){Formatter formatter =newFormatter();for(byte b : hash){
formatter.format("%02x", b);}String result = formatter.toString();
formatter.close();return result;}
Ini sedikit lebih fleksibel dari jawaban yang diterima. Secara pribadi, saya menyimpan jawaban yang diterima dan kelebihan ini, dapat digunakan dalam lebih banyak konteks.
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
Menambahkan toples utilitas untuk fungsi sederhana bukanlah pilihan yang baik. Alih-alih merakit kelas utilitas Anda sendiri. berikut ini mungkin implementasi lebih cepat.
Varian kecil dari solusi yang diajukan oleh @maybewecouldstealavan, yang memungkinkan Anda secara visual menggabungkan N byte bersama-sama dalam string hex output:
Tidak dapat menemukan solusi pada halaman ini yang tidak
Gunakan satu lingkaran
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;importstatic java.lang.System.out;publicfinalclassApp2{// | proposed solution.publicstaticString encode(byte[] bytes){finalint length = bytes.length;// | BigInteger constructor throws if it is given an empty array.if(length ==0){return"00";}finalint evenLength =(int)(2*Math.ceil(length /2.0));finalString format ="%0"+ evenLength +"x";finalString result =String.format (format,newBigInteger(bytes));return result;}publicstaticvoid main(String[] args)throwsException{// 00
out.println(encode(newbyte[]{}));// 01
out.println(encode(newbyte[]{1}));//203040
out.println(encode(newbyte[]{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).
publicstaticString encode(byte[] bytes){finalint length = bytes.length;// | BigInteger constructor throws if it is given an empty array.if(length ==0){return"00";}returnnewBigInteger(bytes).toString(16);}
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.
publicstaticString bytesToHex(finalbyte[] bytes){finalint numBytes = bytes.length;finalchar[] container =newchar[numBytes *2];for(int i =0; i < numBytes; i++){finalint b = bytes[i]&0xFF;
container[i *2]=Character.forDigit(b >>>4,0x10);
container[i *2+1]=Character.forDigit(b &0xF,0x10);}returnnewString(container);}
publicstaticbyte[] hexStringToByteArray(String s){int len = s.length();byte[] data =newbyte[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;}
privatestaticString bytesToHexString(byte[] bytes,int length){if(bytes ==null|| length ==0)returnnull;StringBuilder ret =newStringBuilder(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();}
toHexString(...)
metode yang dapat membantu jika ini yang Anda cari. JugaString.format(...)
dapat melakukan beberapa trik format rapi menggunakan%2x
string kode.Jawaban:
Dari diskusi di sini , dan terutama ini jawabannya, ini adalah fungsi saya gunakan saat ini:
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:
sumber
String printHexBinary(byte[])
danbyte[] parseHexBinary(String)
.printHexBinary
Namun, jauh lebih lambat (2x) dari fungsi dalam jawaban ini. (Saya memeriksa sumbernya; ia menggunakanstringBuilder
.parseHexBinary
Menggunakan array.) Sungguh, untuk sebagian besar tujuan itu cukup cepat dan Anda mungkin sudah memilikinya.printHexBinary
?javax.xml.bind.DataTypeConverter
sedang dihapus dari Jawa 11.The Apache Commons Codec perpustakaan memiliki Hex kelas untuk melakukan hal ini jenis pekerjaan.
sumber
import org.apache.commons.codec.*;
Anda bisa melakukannyaimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
iniString toHexString(byte[] data)
Metode
javax.xml.bind.DatatypeConverter.printHexBinary()
, bagian dari Arsitektur Java untuk XML Binding (JAXB) , adalah cara yang mudah untuk mengkonversibyte[]
ke string hex. TheDatatypeConverter
kelas 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.bind
tidak ada, dan jika Anda ingin menggunakan JAXB, yang berisiDatatypeConverter
, Anda harus menginstal JAXB API dan JAXB Runtime dari Maven.Contoh penggunaan:
Akan menghasilkan:
Jawaban ini sama dengan yang ini .
sumber
Solusi paling sederhana, tidak ada lib eksternal, tanpa konstanta digit:
sumber
Solusi Jambu Biji, untuk kelengkapan:
Sekarang
hex
adalah"48656c6c6f20776f726c64"
.sumber
new HashCode(bytes).toString()
.HashCode.fromBytes(checksum).toString()
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
sumber
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
BigInteger
representasi hex 's: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.
000AE3
Vs0AE3
untuk 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+).
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:
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:
Opsi 5: Google Guava
Lebih sering daripada tidak Anda sudah memiliki jambu biji sebagai ketergantungan. Jika demikian gunakan saja:
Opsi 6: Keamanan Musim Semi
Jika Anda menggunakan kerangka kerja Spring dengan Keamanan Spring Anda dapat menggunakan yang berikut ini:
Opsi 7: Bouncy Castle
Jika Anda sudah menggunakan kerangka keamanan Bouncy Castle Anda dapat menggunakan
Hex
utilnya: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:
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.
Spesifikasi: JDK 8u202, i7-7700K, Win10, 24GB Ram. Lihat patokan lengkap di sini .
sumber
Gunakan kelas DataTypeConverter
javax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
sumber
Saya akan menggunakan sesuatu seperti ini untuk panjang tetap, seperti hash:
sumber
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:
sumber
if (raw == null) return null
tidak gagal dengan cepat. Mengapa Anda pernah menggunakannull
kunci?Dengan biaya kecil menyimpan tabel pencarian implementasi ini sederhana dan sangat cepat.
sumber
BYTE2HEX
array denganfor
siklus sederhana ?static { }
blok.Bagaimana dengan ini?
sumber
Kita tidak perlu menggunakan pustaka eksternal atau menulis kode berdasarkan loop dan konstanta.
Cukup ini saja:
sumber
Saya lebih suka menggunakan ini:
Ini sedikit lebih fleksibel dari jawaban yang diterima. Secara pribadi, saya menyimpan jawaban yang diterima dan kelebihan ini, dapat digunakan dalam lebih banyak konteks.
sumber
Saya biasanya menggunakan metode berikut untuk pernyataan debuf, tetapi saya tidak tahu apakah itu cara terbaik untuk melakukannya atau tidak
sumber
StringBuilder buf = new StringBuilder(data.length * 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
mungkin kamu memang punya ...
sumber
Jika Anda menggunakan kerangka kerja Spring Security, Anda dapat menggunakan:
sumber
Menambahkan toples utilitas untuk fungsi sederhana bukanlah pilihan yang baik. Alih-alih merakit kelas utilitas Anda sendiri. berikut ini mungkin implementasi lebih cepat.
sumber
Varian kecil dari solusi yang diajukan oleh @maybewecouldstealavan, yang memungkinkan Anda secara visual menggabungkan N byte bersama-sama dalam string hex output:
Itu adalah:
sumber
Tidak dapat menemukan solusi pada halaman ini yang tidak
Inilah solusi yang tidak memiliki kekurangan di atas (tidak ada janji saya tidak memiliki kekurangan lain sekalipun)
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).
sumber
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.sumber
// Menggeser byte lebih efisien // Anda dapat menggunakan ini juga
sumber
Jika Anda mencari array byte persis seperti ini untuk python, saya telah mengubah implementasi Java ini menjadi python.
sumber
sumber
Berikut ini adalah
java.util.Base64
implementasi seperti (sebagian), bukan?sumber
sumber
sumber