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
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
Jawaban:
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);
}
String printHexBinary(byte[])
dan byte[] parseHexBinary(String)
. printHexBinary
Namun, jauh lebih lambat (2x) dari fungsi dalam jawaban ini. (Saya memeriksa sumbernya; ia menggunakan stringBuilder
. 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.
import org.apache.commons.codec.binary.Hex;
String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );
import org.apache.commons.codec.*;
Anda bisa melakukannyaimport org.apache.commons.codec.binary.Hex;
org.bouncycastle.util.encoders.Hex
ini String toHexString(byte[] data)
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 DatatypeConverter
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 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 .
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();
}
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 hex
adalah "48656c6c6f20776f726c64"
.
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
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.
Satu solusi yang sangat sederhana adalah dengan menggunakan BigInteger
representasi 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. 000AE3
Vs 0AE3
untuk input 3 byte). Ini juga sangat lambat, sekitar 100x lebih lambat dibandingkan dengan opsi berikutnya.
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 .
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 .
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));
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);
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));
Jika Anda sudah menggunakan kerangka keamanan Bouncy Castle Anda dapat menggunakan Hex
utilnya:
import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);
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 .
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 .
Gunakan kelas DataTypeConverterjavax.xml.bind.DataTypeConverter
String hexString = DatatypeConverter.printHexBinary(bytes[] raw);
Saya akan menggunakan sesuatu seperti ini untuk panjang tetap, seperti hash:
md5sum = String.format("%032x", new BigInteger(1, md.digest()));
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();
}
if (raw == null) return null
tidak gagal dengan cepat. Mengapa Anda pernah menggunakan null
kunci?
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);
}
BYTE2HEX
array dengan for
siklus sederhana ?
static { }
blok.
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;
}
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.
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();
}
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
org.apache.commons.codec.binary.Hex
mungkin kamu memang punya ...
org.apache.xerces.impl.dv.util.HexBin
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));
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));
}
}
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
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)
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);
}
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);
}
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=[])
Berikut ini adalah java.util.Base64
implementasi 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;
}
//...
}
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();
}
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);
}
toHexString(...)
metode yang dapat membantu jika ini yang Anda cari. JugaString.format(...)
dapat melakukan beberapa trik format rapi menggunakan%2x
string kode.