Kode Java Untuk mengkonversi byte ke Hexadecimal


184

Saya memiliki array byte. Saya ingin setiap byte String array yang akan dikonversi ke nilai heksadesimal yang sesuai.

Apakah ada fungsi di Jawa untuk mengubah array byte ke Hexadecimal?


2
Apa yang Anda sebut byte-array di Jawa disebut byte string dalam bahasa lain (mis. Docs.racket-lang.org/guide/bytestrings.html )
Patrick Favre

Jawaban:


311
    byte[] bytes = {-1, 0, 1, 2, 3 };
    StringBuilder sb = new StringBuilder();
    for (byte b : bytes) {
        sb.append(String.format("%02X ", b));
    }
    System.out.println(sb.toString());
    // prints "FF 00 01 02 03 "

Lihat juga

  • java.util.Formatter sintaksis
    • %[flags][width]conversion
      • Bendera '0'- Hasilnya akan menjadi nol-empuk
      • Lebar 2
      • Konversi 'X'- Hasilnya diformat sebagai bilangan bulat heksadesimal, huruf besar

Melihat teks pertanyaan, mungkin juga inilah yang diminta:

    String[] arr = {"-1", "0", "10", "20" };
    for (int i = 0; i < arr.length; i++) {
        arr[i] = String.format("%02x", Byte.parseByte(arr[i]));
    }
    System.out.println(java.util.Arrays.toString(arr));
    // prints "[ff, 00, 0a, 14]"

Beberapa jawaban di sini menggunakan Integer.toHexString(int); ini bisa dilakukan, tetapi dengan beberapa peringatan. Karena parameternya adalah int, konversi pelebaran primitif dilakukan ke byteargumen, yang melibatkan ekstensi tanda.

    byte b = -1;
    System.out.println(Integer.toHexString(b));
    // prints "ffffffff"

8-bit byte, yang masuk dalam Java, diperpanjang-sign menjadi 32-bit int. Untuk secara efektif membatalkan ekstensi tanda ini, seseorang dapat menutupi bytedengan 0xFF.

    byte b = -1;
    System.out.println(Integer.toHexString(b & 0xFF));
    // prints "ff"

Masalah lain dengan menggunakan toHexStringadalah bahwa hal itu tidak sesuai dengan nol:

    byte b = 10;
    System.out.println(Integer.toHexString(b & 0xFF));
    // prints "a"

Kedua faktor yang digabungkan harus membuat String.formatsolusi lebih disukai.

Referensi


@Vivek: apa itu "nilai yang sangat besar"? Apa input dan apa outputnya?
polygenelubricants

Biarkan saya jelaskan lagi .. Saya memiliki koleksi string byte dalam sebuah array. Tapi apa yang harus saya lakukan adalah menganalisis setiap byte secara terpisah .. Jadi, saya tidak ingin bekerja pada seluruh array, tetapi setiap byte byte string pada suatu waktu, itu adalah salah satu komponen dari array itu .. Kebingungan muncul karena kata " Himpunan". Sekarang dalam kode di bawah ini "byte bv = 10; String hexString = Integer.toHexString (bv);" CAse 1 (Byte Diterima: 68 Hex Output:: 44) Kasus: 2 (Byte diterima: -46 Hex Output:: ffffffd2) ......... Mengapa saya mendapatkan hasil yang tidak terduga untuk beberapa nilai?
Vivek

1
@Vivek: baca jawaban saya tentang penggunaan toHexString. Anda harus menutupinya dengan & 0xFF, yaitu Integer.toHexString(-46 & 0xFF)adalah "d2".
polygenelubricants

@polygenelubricants: Terima kasih banyak .. Sepertinya, akhirnya kodenya berfungsi dengan baik .. Apakah aman untuk menggunakan fungsi toHexString sekarang? Atau, mungkin ada beberapa celah dengan pendekatan itu?
Vivek

1
@Vivek: "aman", Anda hanya perlu berhati-hati dan memastikan Anda selalu menyembunyikan bytenilainya & 0xFF. yang formatsolusi di atas juga mungkin memerlukan masking tergantung pada apa yang Anda benar-benar menggunakan sebagai argumen.
polygenelubricants

65

Saya memposting karena tidak ada jawaban yang ada menjelaskan mengapa pendekatan mereka bekerja, yang saya pikir sangat penting untuk masalah ini. Dalam beberapa kasus, ini menyebabkan solusi yang diusulkan tampak rumit dan tidak perlu. Sebagai ilustrasi saya akan memberikan pendekatan yang cukup mudah, tetapi saya akan memberikan sedikit lebih detail untuk membantu menggambarkan mengapa itu bekerja.

Pertama, apa yang kita coba lakukan? Kami ingin mengonversi nilai byte (atau array byte) ke string yang mewakili nilai heksadesimal di ASCII. Jadi langkah pertama adalah untuk mengetahui dengan tepat byte di Java:

Tipe data byte adalah integer komplemen dua-ditandatangani 8-bit . Ini memiliki nilai minimum -128 dan nilai maksimum 127 (inklusif). Tipe data byte dapat berguna untuk menghemat memori dalam array besar, di mana penghematan memori sebenarnya penting. Mereka juga dapat digunakan di tempat int di mana batasnya membantu memperjelas kode Anda; fakta bahwa rentang variabel terbatas dapat berfungsi sebagai bentuk dokumentasi.

Apa artinya ini? Beberapa hal: Pertama dan yang paling penting, itu artinya kami bekerja dengan 8-bit . Jadi misalnya kita dapat menulis angka 2 sebagai 0000 0010. Namun, karena ini adalah pelengkap dua, kita menulis negatif 2 seperti ini: 1111 1110. Yang juga berarti adalah bahwa mengkonversi ke hex sangat mudah. Artinya, Anda cukup mengkonversi setiap segmen 4 bit langsung ke hex. Perhatikan bahwa untuk memahami angka negatif dalam skema ini, Anda harus terlebih dahulu memahami komplemen dua. Jika Anda belum memahami komplemen dua, Anda dapat membaca penjelasan yang sangat baik, di sini: http://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html


Mengubah Pelengkap Dua menjadi Hex Secara Umum

Setelah angka ada dalam komplemen dua, mati sederhana untuk mengubahnya menjadi hex. Secara umum, mengkonversi dari biner ke hex sangat mudah, dan seperti yang akan Anda lihat dalam dua contoh berikutnya, Anda dapat langsung beralih dari komplemen dua ke hex.

Contohnya

Contoh 1: Konversi 2 menjadi Hex.

1) Konversi 2 menjadi biner pertama dalam komplemen dua:

2 (base 10) = 0000 0010 (base 2)

2) Sekarang konversikan biner ke hex:

0000 = 0x0 in hex
0010 = 0x2 in hex

therefore 2 = 0000 0010 = 0x02. 

Contoh 2: Konversi -2 (dalam komplemen dua) ke Hex.

1) Konversi -2 ke biner pertama dalam komplemen dua:

-2 (base 10) = 0000 0010 (direct conversion to binary) 
               1111 1101 (invert bits)
               1111 1110 (add 1)
therefore: -2 = 1111 1110 (in two's complement)

2) Sekarang Konversikan ke Hex:

1111 = 0xF in hex
1110 = 0xE in hex

therefore: -2 = 1111 1110 = 0xFE.


Melakukan ini Di Jawa

Sekarang setelah kita membahas konsepnya, Anda akan menemukan bahwa kita dapat mencapai apa yang kita inginkan dengan beberapa penyamaran dan pengubahan sederhana. Hal utama yang perlu dipahami adalah bahwa byte yang Anda coba konversi sudah ada dalam komplemen dua. Anda tidak melakukan konversi ini sendiri. Saya pikir ini adalah titik utama kebingungan tentang masalah ini. Ambil contoh array byte berikut:

byte[] bytes = new byte[]{-2,2};

Kami baru saja mengonversinya secara manual menjadi hex, di atas, tetapi bagaimana kami melakukannya di Java? Begini caranya:

Langkah 1: Buat StringBuffer untuk menampung perhitungan kami.

StringBuffer buffer = new StringBuffer();

Langkah 2: Mengisolasi bit urutan yang lebih tinggi, mengubahnya menjadi hex, dan menambahkannya ke buffer

Mengingat angka biner 1111 1110, kita dapat mengisolasi bit urutan yang lebih tinggi dengan terlebih dahulu menggesernya dengan 4, dan kemudian mem-nolkan sisa angka tersebut. Secara logis ini sederhana, namun, detail implementasi di Jawa (dan banyak bahasa) memperkenalkan kerutan karena ekstensi tanda. Pada dasarnya, ketika Anda menggeser nilai byte, Java pertama kali mengkonversi nilai Anda ke integer, dan kemudian melakukan ekstensi tanda. Jadi, sementara Anda mengharapkan 1111 1110 >> 4 menjadi 0000 1111, pada kenyataannya, di Jawa itu diwakili sebagai pelengkap keduanya 0xFFFFFFFF!

Jadi kembali ke contoh kita:

1111 1110 >> 4 (shift right 4) = 1111 1111 1111 1111 1111 1111 1111 1111 (32 bit sign-extended number in two's complement)

Kami kemudian dapat mengisolasi bit dengan topeng:

1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111
therefore: 1111 = 0xF in hex. 

Di Jawa kita bisa melakukan ini semua dalam satu kesempatan:

Character.forDigit((bytes[0] >> 4) & 0xF, 16);

Fungsi forDigit hanya memetakan angka yang Anda berikan ke himpunan angka heksadesimal 0-F.

Langkah 3: Selanjutnya kita perlu mengisolasi bit urutan lebih rendah. Karena bit yang kita inginkan sudah dalam posisi yang benar, kita bisa menutupinya:

1111 1110 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1110 (recall sign extension from before)
therefore: 1110 = 0xE in hex.  

Seperti sebelumnya, di Jawa kita bisa melakukan ini semua dalam satu kesempatan:

Character.forDigit((bytes[0] & 0xF), 16);

Dengan menggabungkan semua ini, kita bisa melakukannya sebagai for loop dan mengonversi seluruh array:

for(int i=0; i < bytes.length; i++){
    buffer.append(Character.forDigit((bytes[i] >> 4) & 0xF, 16));
    buffer.append(Character.forDigit((bytes[i] & 0xF), 16));
}

Semoga penjelasan ini membuat segalanya menjadi lebih jelas bagi Anda yang bertanya-tanya apa yang sedang terjadi dalam banyak contoh yang akan Anda temukan di internet. Semoga saya tidak membuat kesalahan yang mengerikan, tetapi saran dan koreksi sangat kami harapkan!


4
jawaban Terbaik! Implementasi simetrik dari String hex ke byte akan dikonversi kemudian gunakan Character.digit(), seperti(byte) ((Character.digit(str.charAt(0), 16) << 4) + Character.digit(str.charAt(1), 16))
ericbn

21

Cara tercepat yang saya temukan untuk melakukan ini adalah sebagai berikut:

private static final String    HEXES    = "0123456789ABCDEF";

static String getHex(byte[] raw) {
    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();
}

Ini ~ 50x lebih cepat dari String.format. jika Anda ingin mengujinya:

public class MyTest{
    private static final String    HEXES        = "0123456789ABCDEF";

    @Test
    public void test_get_hex() {
        byte[] raw = {
            (byte) 0xd0, (byte) 0x0b, (byte) 0x01, (byte) 0x2a, (byte) 0x63,
            (byte) 0x78, (byte) 0x01, (byte) 0x2e, (byte) 0xe3, (byte) 0x6c,
            (byte) 0xd2, (byte) 0xb0, (byte) 0x78, (byte) 0x51, (byte) 0x73,
            (byte) 0x34, (byte) 0xaf, (byte) 0xbb, (byte) 0xa0, (byte) 0x9f,
            (byte) 0xc3, (byte) 0xa9, (byte) 0x00, (byte) 0x1e, (byte) 0xd5,
            (byte) 0x4b, (byte) 0x89, (byte) 0xa3, (byte) 0x45, (byte) 0x35,
            (byte) 0xd6, (byte) 0x10,
        };

        int N = 77777;
        long t;

        {
            t = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                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)));
                }
                hex.toString();
            }
            System.out.println(System.currentTimeMillis() - t); // 50
        }

        {
            t = System.currentTimeMillis();
            for (int i = 0; i < N; i++) {
                StringBuilder hex = new StringBuilder(2 * raw.length);
                for (byte b : raw) {
                    hex.append(String.format("%02X", b));
                }
                hex.toString();
            }
            System.out.println(System.currentTimeMillis() - t); // 2535
        }

    }
}

Sunting : Baru saja menemukan sesuatu yang lebih cepat dan tahan pada satu baris tetapi tidak kompatibel dengan JRE 9. Gunakan dengan risiko Anda sendiri

import javax.xml.bind.DatatypeConverter;

DatatypeConverter.printHexBinary(raw);

2
DatatypeConverter tidak lagi tersedia di Java 9. Yang berbahaya adalah kode yang menggunakannya akan dikompilasi di bawah Java 1.8 atau lebih awal (Java 9 dengan pengaturan sumber sebelumnya), tetapi mendapatkan pengecualian runtime di bawah Java 9.
Stephen M -on strike-

Poin kedua @StephenMs saya: menggunakan ini dengan jre9 akan macet dengan ClassNotFound Exception
Patrick Favre

Sebenarnya dapat dengan mudah mengekstrak metode kode sumber printHexBinary dari src.zip dari jdk, yang tampaknya 1 kali lebih cepat dari metode 1.
Buah

1
Jika Anda bekerja dengan array char untuk HEXES konstan, bukannya String dan charAt (), Anda mendapatkan ~ 20% lebih banyak kecepatan.
Dyorgio

15

Coba dengan cara ini:

byte bv = 10;
String hexString = Integer.toHexString(bv);

Berurusan dengan array (jika saya mengerti Anda dengan benar):

byte[] bytes = {9, 10, 11, 15, 16};
StringBuffer result = new StringBuffer();
for (byte b : bytes) {
    result.append(String.format("%02X ", b));
    result.append(" "); // delimiter
}
return result.toString();

Seperti yang disebutkan dalam polygenelubricants, String.format()adalah jawaban yang benar dibandingkan Integer.toHexString()(karena berurusan dengan angka negatif dengan cara yang benar).


2
Tanda ini akan diperluas, mis -1. Coba .
polygenelubricants

byte bv = 10; String hexString = Integer.toHexString (bv); Ini tampaknya bekerja firne .. Saya bisa menerapkannya secara individual pada setiap elemen array .. Kode lain (Berurusan dengan array) mengembalikan nilai terlalu besar. Apa yang bisa menjadi alasan untuk itu?
Vivek

@Vivek, itu karena dalam kasus bvitu mengembalikan karakter heksadesimal tunggal . Sedangkan sisa kode mengembalikan serangkaian karakter heksadesimal . Saya telah mengubah kode dengan delimeter sehingga Anda dapat memahaminya sekarang.
0x2D9A3

@Bar: Anda masih dapat menggunakan Integer.toHexStringjika Anda menyembunyikan bytedengan 0xFFuntuk membatalkan ekstensi ekstensi.
polygenelubricants

CAse 1 (Byte Received: 68 Hex Output:: 44) Kasus: 2 (Byte Received: -46 Hex Output:: ffffffd2) Saya mendapatkan nilai output yang tidak terduga jika array byte negatif ... Bagaimana menangani ini?
Vivek

13

Solusi terbaik adalah one-liner badass ini:

String hex=DatatypeConverter.printHexBinary(byte[] b);

seperti yang disebutkan di sini


4
DatatypeConverter tidak lagi tersedia di Java 9. Yang berbahaya adalah kode yang menggunakannya akan dikompilasi di bawah Java 1.8 atau lebih awal (Java 9 dengan pengaturan sumber sebelumnya), tetapi mendapatkan pengecualian runtime di bawah Java 9.
Stephen M -on strike-

Sedih ketika Anda mengatakan itu tidak di jdk9. new BigInteger(byteArray).toString(16)adalah cara untuk pergi. Apakah ada masalah dengan itu ??
prayagupd

Mungkin bukan masalah perf, tetapi akan melewatkan angka nol di depan (karena tidak ada artinya bagi nomor seperti BigInteger)
Friso

Sepertinya itu masih dalam java 9 docs , jadi sepertinya tidak apa-apa untuk menggunakannya dari apa yang saya tahu
Brad Parks

saya pikir seperti dijelaskan di sini masih ok untuk digunakan untuk java9, tetapi akan dihapus dalam rilis java masa depan. Anda juga masih dapat menggunakannya dengan modul jaxb mandiri 'baru' pada versi 2.3.0 .
lynx

11

Jika Anda menginginkan representasi hex lebar konstan, yaitu 0Aalih-alih A, sehingga Anda dapat memulihkan byte secara jelas, coba format():

StringBuilder result = new StringBuilder();
for (byte bb : byteArray) {
    result.append(String.format("%02X", bb));
}
return result.toString();

11

Cara singkat dan sederhana untuk mengkonversi byte[]ke string hex dengan menggunakan BigInteger:

import java.math.BigInteger;

byte[] bytes = new byte[] {(byte)255, 10, 20, 30};
String hex = new BigInteger(1, bytes).toString(16);
System.out.println(hex); // ff0a141e

Bagaimana itu bekerja?

Kelas java.math.BigIntegerkelas sistem bawaan ( java.math.BigInteger ) kompatibel dengan data biner dan hex:

  • Memiliki konstruktor BigInteger(signum=1, byte[])untuk membuat bilangan bulat besar dengan byte[](atur parameter pertama signum= 1untuk menangani dengan benar byte negatif)
  • Gunakan BigInteger.toString(16)untuk mengonversi bilangan bulat besar menjadi string hex
  • Untuk menguraikan penggunaan nomor hex new BigInteger("ffa74b", 16)- tidak menangani dengan benar nol di depannya

Jika Anda mungkin ingin memiliki nol di depan dalam hasil hex, periksa ukurannya dan tambahkan nol yang hilang jika perlu:

if (hex.length() % 2 == 1)
    hex = "0" + hex;

Catatan

Gunakan new BigInteger(1, bytes), alih-alih new BigInteger(bytes), karena Java " rusak karena desain " dan bytetipe data tidak menampung byte tetapi menandatangani bilangan bulat kecil [-128 ... 127]. Jika byte pertama negatif, BigIntegeranggap Anda melewatkan bilangan bulat besar negatif. Cukup berikan 1sebagai parameter pertama ( signum=1).

Konversi kembali dari hex kebyte[] rumit: kadang-kadang nol terkemuka masuk dalam output yang dihasilkan dan harus dibersihkan seperti ini:

byte[] bytes = new BigInteger("ffa74b", 16).toByteArray();
if (bytes[0] == 0) {
    byte[] newBytes = new byte[bytes.length - 1];
    System.arraycopy(bytes, 1, newBytes, 0, newBytes.length);
    bytes = newBytes;
}

Catatan terakhir adalah jika byte[]memiliki beberapa nol terkemuka, mereka akan hilang.


1
Jika byte terkemuka memiliki nilai desimal kurang dari 16, Anda juga akan mendapatkan string dengan jumlah ganjil karakter hex.
Alex Jorgenson

8

Jika Anda senang menggunakan perpustakaan eksternal, org.apache.commons.codec.binary.Hexkelas memiliki encodeHexmetode yang mengambil a byte[]dan mengembalikan a char[]. Metode ini JAUH lebih cepat daripada opsi format, dan merangkum detail konversi. Juga dilengkapi dengan decodeHexmetode untuk konversi yang berlawanan.


4
Cara yang lebih mudah adalah menggunakan fungsi bawaan javax.xml.bind.DatatypeConverter / parseHexBinary dan printHexBinary. Lihat stackoverflow.com/questions/9655181/…
Alan Thompson

2
Beri +1 ke opsi ini. Hex juga memiliki metode encodeHexString, yang mengambil byte [] dan mengembalikan sebuah String.
Mingjiang Shi

jangan lupa bahwa javaxnamespace tidak selalu tersedia.
Mene

7

Anda dapat menggunakan metode ini dari perpustakaan Bouncy Castle Provider :

org.bouncycastle.util.encoders.Hex.toHexString(byteArray);

Paket Bouncy Castle Crypto adalah implementasi Java dari algoritma kriptografi. Guci ini berisi penyedia JCE dan API ringan untuk API Kriptografi Bouncy Castle untuk JDK 1.5 hingga JDK 1.8.

Ketergantungan maven:

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcprov-jdk15on</artifactId>
    <version>1.60</version>
</dependency>

atau dari Apache Commons Codec :

org.apache.commons.codec.binary.Hex.encodeHexString(byteArray);

Paket Apache Commons Codec berisi encoder dan decoder sederhana untuk berbagai format seperti Base64 dan Hexadecimal. Selain encoder dan decoder yang banyak digunakan ini, paket codec juga memelihara koleksi utilitas enkode fonetik.

Ketergantungan maven:

<dependency>
    <groupId>commons-codec</groupId>
    <artifactId>commons-codec</artifactId>
    <version>1.11</version>
</dependency>

Ya, ini adalah solusi terbaik , tetapi membutuhkan perpustakaan eksternal: Apache Commons Codec ( mvnrepository.com/artifact/commons-codec/commons-codec/1.11 ) atau Penyedia BouncyCastle ( mvnrepository.com/artifact/org.bouncycastle/bcprov- jdk15on / 1.60 )
Svetlin Nakov

5

Ini adalah kode yang saya temukan untuk menjalankan tercepat sejauh ini. Saya menjalankannya pada 109015 byte array dengan panjang 32, dalam 23ms. Saya menjalankannya pada VM sehingga mungkin akan berjalan lebih cepat pada bare metal.

public static final char[] HEX_DIGITS =         {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

public static char[] encodeHex( final byte[] data ){
    final int l = data.length;
    final char[] out = new char[l<<1];
    for( int i=0,j=0; i<l; i++ ){
        out[j++] = HEX_DIGITS[(0xF0 & data[i]) >>> 4];
        out[j++] = HEX_DIGITS[0x0F & data[i]];
    }
    return out;
}

Maka Anda bisa melakukannya

String s = new String( encodeHex(myByteArray) );

3
BigInteger n = new BigInteger(byteArray);
String hexa = n.toString(16));

Tidak berfungsi: BigInteger(byteArrayOf(-1, 2, 3, 4, 5)).toString(16)pengembalian"-fdfcfbfb"
Martin Vysny

Ini hasil yang benar. Anda bekerja dengan byte '-1', '2' ... '5'. Thats bytes tidak memiliki visualiztion ( unicode.org ) jika Anda berniat bekerja dengan literal '-1', '2' ... '5' Anda harus bekerja dengan nilai string.
Wender

Itu adalah hasil yang salah. Nilai byte Java -1 sebenarnya 0xFF (sama dengan (int) 255) karena byte Java ditandatangani, jadi hasilnya seharusnya FF02030405. Jika Anda mencoba solusi @Jerinaw di atas Anda akan melihatnya akan mencetak output yang benar. Lihat juga solusi Svetlin Nakov di bawah ini.
Martin Vysny

2

Berikut adalah fungsi sederhana untuk mengkonversi byte ke Hexadecimal

   private static String convertToHex(byte[] data) {
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; i++) {
        int halfbyte = (data[i] >>> 4) & 0x0F;
        int two_halfs = 0;
        do {
            if ((0 <= halfbyte) && (halfbyte <= 9))
                buf.append((char) ('0' + halfbyte));
            else
                buf.append((char) ('a' + (halfbyte - 10)));
            halfbyte = data[i] & 0x0F;
        } while(two_halfs++ < 1);
    }
    return buf.toString();
}

2

Yang lain sudah membahas kasus umum. Tetapi jika Anda memiliki larik byte bentuk yang dikenal, misalnya alamat MAC, maka Anda dapat:

byte[] mac = { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 };

String str = String.format("%02X:%02X:%02X:%02X:%02X:%02X",
                           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 

1

Membuat (dan menghancurkan) banyak Stringcontoh bukanlah cara yang baik jika kinerja adalah masalah.

Harap abaikan argumen verbose (duplikat) yang memeriksa pernyataan if. Itu untuk tujuan pendidikan (lain).

Proyek pakar penuh: http://jinahya.googlecode.com/svn/trunk/com.googlecode.jinahya/hex-codec/

Pengodean ...

/**
 * Encodes a single nibble.
 *
 * @param decoded the nibble to encode.
 *
 * @return the encoded half octet.
 */
protected static int encodeHalf(final int decoded) {

    switch (decoded) {
        case 0x00:
        case 0x01:
        case 0x02:
        case 0x03:
        case 0x04:
        case 0x05:
        case 0x06:
        case 0x07:
        case 0x08:
        case 0x09:
            return decoded + 0x30; // 0x30('0') - 0x39('9')
        case 0x0A:
        case 0x0B:
        case 0x0C:
        case 0x0D:
        case 0x0E:
        case 0x0F:
            return decoded + 0x57; // 0x41('a') - 0x46('f')
        default:
            throw new IllegalArgumentException("illegal half: " + decoded);
    }
}


/**
 * Encodes a single octet into two nibbles.
 *
 * @param decoded the octet to encode.
 * @param encoded the array to which each encoded nibbles are written.
 * @param offset the offset in the array.
 */
protected static void encodeSingle(final int decoded, final byte[] encoded,
                                   final int offset) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if (encoded.length < 2) {
        // not required
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") < 2");
    }

    if (offset < 0) {
        throw new IllegalArgumentException("offset(" + offset + ") < 0");
    }

    if (offset >= encoded.length - 1) {
        throw new IllegalArgumentException(
            "offset(" + offset + ") >= encoded.length(" + encoded.length
            + ") - 1");
    }

    encoded[offset] = (byte) encodeHalf((decoded >> 4) & 0x0F);
    encoded[offset + 1] = (byte) encodeHalf(decoded & 0x0F);
}


/**
 * Decodes given sequence of octets into a sequence of nibbles.
 *
 * @param decoded the octets to encode
 *
 * @return the encoded nibbles.
 */
protected static byte[] encodeMultiple(final byte[] decoded) {

    if (decoded == null) {
        throw new IllegalArgumentException("null decoded");
    }

    final byte[] encoded = new byte[decoded.length << 1];

    int offset = 0;
    for (int i = 0; i < decoded.length; i++) {
        encodeSingle(decoded[i], encoded, offset);
        offset += 2;
    }

    return encoded;
}


/**
 * Encodes given sequence of octets into a sequence of nibbles.
 *
 * @param decoded the octets to encode.
 *
 * @return the encoded nibbles.
 */
public byte[] encode(final byte[] decoded) {

    return encodeMultiple(decoded);
}

Mendekodekan ...

/**
 * Decodes a single nibble.
 *
 * @param encoded the nibble to decode.
 *
 * @return the decoded half octet.
 */
protected static int decodeHalf(final int encoded) {

    switch (encoded) {
        case 0x30: // '0'
        case 0x31: // '1'
        case 0x32: // '2'
        case 0x33: // '3'
        case 0x34: // '4'
        case 0x35: // '5'
        case 0x36: // '6'
        case 0x37: // '7'
        case 0x38: // '8'
        case 0x39: // '9'
            return encoded - 0x30;
        case 0x41: // 'A'
        case 0x42: // 'B'
        case 0x43: // 'C'
        case 0x44: // 'D'
        case 0x45: // 'E'
        case 0x46: // 'F'
            return encoded - 0x37;
        case 0x61: // 'a'
        case 0x62: // 'b'
        case 0x63: // 'c'
        case 0x64: // 'd'
        case 0x65: // 'e'
        case 0x66: // 'f'
            return encoded - 0x57;
        default:
            throw new IllegalArgumentException("illegal half: " + encoded);
    }
}


/**
 * Decodes two nibbles into a single octet.
 *
 * @param encoded the nibble array.
 * @param offset the offset in the array.
 *
 * @return decoded octet.
 */
protected static int decodeSingle(final byte[] encoded, final int offset) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if (encoded.length < 2) {
        // not required
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") < 2");
    }

    if (offset < 0) {
        throw new IllegalArgumentException("offset(" + offset + ") < 0");
    }

    if (offset >= encoded.length - 1) {
        throw new IllegalArgumentException(
            "offset(" + offset + ") >= encoded.length(" + encoded.length
            + ") - 1");
    }

    return (decodeHalf(encoded[offset]) << 4)
           | decodeHalf(encoded[offset + 1]);
}


/**
 * Encodes given sequence of nibbles into a sequence of octets.
 *
 * @param encoded the nibbles to decode.
 *
 * @return the encoded octets.
 */
protected static byte[] decodeMultiple(final byte[] encoded) {

    if (encoded == null) {
        throw new IllegalArgumentException("null encoded");
    }

    if ((encoded.length & 0x01) == 0x01) {
        throw new IllegalArgumentException(
            "encoded.length(" + encoded.length + ") is not even");
    }

    final byte[] decoded = new byte[encoded.length >> 1];

    int offset = 0;
    for (int i = 0; i < decoded.length; i++) {
        decoded[i] = (byte) decodeSingle(encoded, offset);
        offset += 2;
    }

    return decoded;
}


/**
 * Decodes given sequence of nibbles into a sequence of octets.
 *
 * @param encoded the nibbles to decode.
 *
 * @return the decoded octets.
 */
public byte[] decode(final byte[] encoded) {

    return decodeMultiple(encoded);
}

1

Ini cara yang sangat cepat. Tidak diperlukan perpustakaan eksternal.

final protected static char[] HEXARRAY = "0123456789abcdef".toCharArray();

    public static String encodeHexString( 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] = HEXARRAY[v >>> 4];
            hexChars[j * 2 + 1] = HEXARRAY[v & 0x0F];
        }
        return new String(hexChars);
    }

1

Saya tidak tahu apa yang sebenarnya Anda maksud dengan byte String, tetapi di sini ada beberapa konversi dari byte ke String dan sebaliknya, tentu saja ada lebih banyak lagi pada dokumentasi resmi

Integer intValue = 149;

Nilai byte yang sesuai adalah:

Byte byteValue = intValue.byteValue(); // this will convert the rightmost byte of the intValue to byte, because Byte is an 8 bit object and Integer is at least 16 bit, and it will give you a signed number in this case -107

dapatkan nilai integer kembali dari variabel Byte:

Integer anInt = byteValue.intValue(); // This will convert the byteValue variable to a signed Integer

Dari Byte dan Integer ke hex String:
Ini adalah cara saya melakukannya:

Integer anInt = 149
Byte aByte = anInt.byteValue();

String hexFromInt = "".format("0x%x", anInt); // This will output 0x95
String hexFromByte = "".format("0x%x", aByte); // This will output 0x95

Mengubah array byte menjadi string hex:
Sejauh yang saya tahu tidak ada fungsi sederhana untuk mengubah semua elemen di dalam array beberapa Objectke elemen yang lain Object, Jadi Anda harus melakukannya sendiri. Anda dapat menggunakan fungsi-fungsi berikut:

Dari byte [] ke String:

    public static String byteArrayToHexString(byte[] byteArray){
        String hexString = "";

        for(int i = 0; i < byteArray.length; i++){
            String thisByte = "".format("%x", byteArray[i]);
            hexString += thisByte;
        }

        return hexString;
    }

Dan dari string hex ke byte []:

public static byte[] hexStringToByteArray(String hexString){
    byte[] bytes = new byte[hexString.length() / 2];

    for(int i = 0; i < hexString.length(); i += 2){
        String sub = hexString.substring(i, i + 2);
        Integer intVal = Integer.parseInt(sub, 16);
        bytes[i / 2] = intVal.byteValue();
        String hex = "".format("0x%x", bytes[i / 2]);
    }

    return bytes;
}  

Sudah terlambat tapi saya harap ini bisa membantu beberapa orang lain;)


1

Inilah metode cepat Anda:

    private static final String[] hexes = 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 hexes[b&0xFF];
    }

1
jelek, tapi mungkin sangat efisien. :-)
Rich S

1

Sama seperti beberapa jawaban lain, saya sarankan untuk menggunakan String.format()dan BigInteger. Tetapi untuk menginterpretasikan array byte sebagai representasi biner big-endian alih-alih representasi biner dua komplemen (dengan signum dan penggunaan rentang nilai hex yang tidak lengkap) gunakan BigInteger (int signum, besarnya [byte]) , bukan BigInteger (byte [] val ) .

Misalnya, untuk array byte dengan panjang 8 gunakan:

String.format("%016X", new BigInteger(1,bytes))

Keuntungan:

  • nol di depan
  • tidak ada signum
  • hanya fungsi bawaan
  • hanya satu baris kode

Kerugian:

  • mungkin ada cara yang lebih efisien untuk melakukan itu

Contoh:

byte[] bytes = new byte[8];
Random r = new Random();
System.out.println("big-endian       | two's-complement");
System.out.println("-----------------|-----------------");
for (int i = 0; i < 10; i++) {
    r.nextBytes(bytes);
    System.out.print(String.format("%016X", new BigInteger(1,bytes)));
    System.out.print(" | ");
    System.out.print(String.format("%016X", new BigInteger(bytes)));
    System.out.println();
}

Contoh output:

big-endian       | two's-complement
-----------------|-----------------
3971B56BC7C80590 | 3971B56BC7C80590
64D3C133C86CCBDC | 64D3C133C86CCBDC
B232EFD5BC40FA61 | -4DCD102A43BF059F
CD350CC7DF7C9731 | -32CAF338208368CF
82CDC9ECC1BC8EED | -7D3236133E437113
F438C8C34911A7F5 | -BC7373CB6EE580B
5E99738BE6ACE798 | 5E99738BE6ACE798
A565FE5CE43AA8DD | -5A9A01A31BC55723
032EBA783D2E9A9F | 032EBA783D2E9A9F
8FDAA07263217ABA | -70255F8D9CDE8546

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.