Pretvaranje između bajtnih nizova i heksadecimalnih nizova u Javi

1. Pregled

U ovom ćemo uputstvu pogledati različite načine pretvaranja bajtnog niza u heksadecimalni Niz, i obrnuto.

Također ćemo razumjeti mehanizam pretvorbe i napisati našu implementaciju da bismo to postigli.

2. Pretvaranje između bajta i heksadecimalnog

Prije svega, pogledajmo logiku pretvorbe između bajtnih i heksadecimalnih brojeva.

2.1. Bajt u heksadecimalni

Bajtovi su 8-bitni cijeli brojevi s potpisom u Javi. Stoga trebamo pretvoriti svaki 4-bitni segment u hex zasebno i povezati ih. Slijedom toga, dobit ćemo dva heksadecimalna znaka nakon pretvorbe.

Na primjer, možemo zapisati 45 kao 0010 1101 u binarnom obliku, a heksadecimalni ekvivalent bit će "2d":

0010 = 2 (baza 10) = 2 (baza 16) 1101 = 13 (baza 10) = d (baza 16) Dakle: 45 = 0010 1101 = 0x2d 

Primijenimo ovu jednostavnu logiku u Javi:

javni String byteToHex (broj bajta) {char [] hexDigits = novi char [2]; hexDigits [0] = Character.forDigit ((broj >> 4) & 0xF, 16); hexDigits [1] = Znak za cifru ((num & 0xF), 16); vrati novi niz (hexDigits); }

Sada, shvatimo gornji kod analizirajući svaku operaciju. Prije svega, stvorili smo niz znakova duljine 2 za spremanje rezultata:

char [] hexDigits = novi char [2];

Zatim smo izolirali bitove višeg reda desnim pomicanjem 4 bita. A onda smo primijenili masku kako bismo izolirali 4 bita nižeg reda. Maskiranje je potrebno jer su negativni brojevi interno predstavljeni kao dodatak dva pozitivnog broja:

hexDigits [0] = Character.forDigit ((broj >> 4) & 0xF, 16);

Zatim preostala 4 bita pretvaramo u heksadecimalne:

hexDigits [1] = Znak za cifru ((num & 0xF), 16);

Konačno, kreiramo Niz objekt iz polja char. A zatim, vratio ovaj objekt kao pretvoreni heksadecimalni niz.

Sada, shvatimo kako će ovo raditi za negativni bajt -4:

hexDigits [0]: 1111 1100 >> 4 = 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 & 0xF = 0000 0000 0000 0000 0000 0000 0000 1111 = 0xf hexDigits [1]: 1111 1100 & 0xF = 0000 1100 = 0xc Prema tome: -4 (baza 10) = 1111 1100 (baza 2) = fc (baza 16)

Također je vrijedno napomenuti da Lik.zaDigit() metoda uvijek vraća mala slova.

2.2. Heksadecimalni u bajt

Sada, pretvorimo heksadecimalnu znamenku u bajt. Kao što znamo, bajt sadrži 8 bitova. Stoga, trebamo dvije heksadecimalne znamenke da stvorimo jedan bajt.

Prije svega, pretvorit ćemo svaku heksadecimalnu znamenku u binarni ekvivalent zasebno.

A zatim, moramo spojiti dva četiri bitna segmenta da bismo dobili ekvivalent bajta:

Heksadecimalno: 2d 2 = 0010 (baza 2) d = 1101 (baza 2) Prema tome: 2d = 0010 1101 (baza 2) = 45

Sada napišimo operaciju na Javi:

javni bajt hexToByte (Niz hexString) {int firstDigit = toDigit (hexString.charAt (0)); int secondDigit = toDigit (hexString.charAt (1)); return (bajt) ((firstDigit << 4) + secondDigit); } private int toDigit (char hexChar) {int znamenka = Character.digit (hexChar, 16); if (znamenka == -1) {baciti novo IllegalArgumentException ("Nevažeći heksadecimalni znak:" + hexChar); } povratna znamenka; }

Razumijemo ovo, jednu po jednu operaciju.

Prije svega, heksadecimalne znakove pretvorili smo u cijele brojeve:

int firstDigit = toDigit (hexString.charAt (0)); int secondDigit = toDigit (hexString.charAt (1));

Tada smo ostavili pomaknutu najznačajniju znamenku za 4 bita. Slijedom toga, binarni prikaz ima nule na četiri najmanje značajna bita.

Zatim smo joj dodali najmanje značajnu znamenku:

return (bajt) ((firstDigit << 4) + secondDigit);

Sada, ispitajmo toDigit () metoda usko. Koristimo Character.digit () metoda za pretvorbu. Ako vrijednost znaka proslijeđena ovoj metodi nije valjana znamenka u navedenom radixu, vraća se -1.

Provjeravamo povratnu vrijednost i izbacujemo iznimku ako je proslijeđena nevaljana vrijednost.

3. Pretvorba između bajtnih nizova i heksadecimalnih Žice

U ovom trenutku znamo pretvoriti bajt u heksadecimalni i obrnuto. Skalirajmo ovaj algoritam i pretvorimo bajtni niz u / iz heksadecimalnog Niz.

3.1. Niz bajtova u heksadecimalni Niz

Moramo se provući kroz niz i generirati heksadecimalni par za svaki bajt:

javni String encodeHexString (bajt [] byteArray) {StringBuffer hexStringBuffer = novi StringBuffer (); for (int i = 0; i <byteArray.length; i ++) {hexStringBuffer.append (byteToHex (byteArray [i])); } return hexStringBuffer.toString (); }

Kao što već znamo, izlaz će uvijek biti malim slovima.

3.2. Heksadecimalni niz u bajtni niz

Prije svega, moramo provjeriti je li duljina heksadecimalne vrijednosti Niz je paran broj. To je zato što je heksadecimalni Niz s neparnom duljinom rezultirat će netočnim prikazom bajta.

Sada ćemo prelistati niz i pretvoriti svaki heksadecimalni par u bajt:

javni bajt [] decodeHexString (String hexString) {if (hexString.length ()% 2 == 1) {throw new IllegalArgumentException ("Dostavljen nevažeći heksadecimalni niz."); } bajt [] bajtova = novi bajt [hexString.length () / 2]; for (int i = 0; i <hexString.length (); i + = 2) {bytes [i / 2] = hexToByte (hexString.substring (i, i + 2)); } povratak bajtova; }

4. Korištenje BigInteger Razred

Možemo stvoriti objekt tipa BigInteger prosljeđivanjem polja znakova i bajtova.

Sada možemo generirati heksadecimalni Niz uz pomoć statičkog formata metode definiranog u Niz razred:

javni String encodeUsingBigIntegerStringFormat (bajt [] bajtova) {BigInteger bigInteger = novi BigInteger (1, bajt); vrati String.format ("% 0" + (bajtovi.duljina << 1) + "x", velikiInteger); }

Navedeni format generirat će šesnaestinu s malim početnim slovima u malim slovima Niz. Također možemo generirati niz velikih slova zamjenom "x" s "X".

Alternativno, mogli smo koristiti toString () metoda iz BigInteger. Suptilno razlika u korištenju toString () metoda je da izlaz nije podstavljen vodećim nulama:

javni String encodeUsingBigIntegerToString (bajt [] bajtova) {BigInteger bigInteger = novi BigInteger (1, bajt); vrati bigInteger.toString (16); }

Sada, pogledajmo heksadecimalnu Niz do bajt Pretvorba niza:

javni bajt [] decodeUsingBigInteger (niz hexString) {bajt [] byteArray = novi BigInteger (hexString, 16) .toByteArray (); if (byteArray [0] == 0) {byte [] output = novi bajt [byteArray.length - 1]; System.arraycopy (byteArray, 1, output, 0, output.length); povratni izlaz; } return byteArray; }

The toByteArray () metoda daje dodatni znakovni bit. Napisali smo specifični kôd za rukovanje ovim dodatnim bitom.

Stoga bismo trebali biti svjesni ovih detalja prije nego što upotrijebimo BigInteger klasa za pretvorbu.

5. Korištenje DataTypeConverter Razred

The DataTypeConverter klasa se isporučuje s JAXB knjižnicom. Ovo je dio standardne biblioteke do Jave 8. Moramo dodati, počevši od Jave 9 java.xml.bind modul za vrijeme izvođenja.

Pogledajmo implementaciju pomoću DataTypeConverter razred:

javni String encodeUsingDataTypeConverter (bajt [] bajtova) {return DatatypeConverter.printHexBinary (bajtova); } javni bajt [] decodeUsingDataTypeConverter (String hexString) {return DatatypeConverter.parseHexBinary (hexString); }

Kao što je prikazano gore, vrlo je prikladan za upotrebu DataTypeConverter razred. The izlaz iz printHexBinary () metoda je uvijek velikim slovom. Ova klasa nudi skup metoda ispisa i raščlanjivanja za pretvorbu tipa podataka.

Prije odabira ovog pristupa moramo se pobrinuti da klasa bude dostupna tijekom izvođenja.

6. Korištenje Apacheove biblioteke Commons-Codec

Možemo koristiti Hex klasa isporučena s bibliotekom zajedničkog kodeka Apache:

javni String encodeUsingApacheCommons (bajt [] bajtova) baca DecoderException {return Hex.encodeHexString (bajtova); } javni bajt [] decodeUsingApacheCommons (String hexString) baca DecoderException {return Hex.decodeHex (hexString); }

The izlaz od encodeHexString je uvijek malim slovom.

7. Korištenje Googleove knjižnice Guava

Pogledajmo kako BaseEncoding klasa može se koristiti za kodiranje i dekodiranje bajt polja u heksadecimalni Niz:

javni String encodeUsingGuava (bajt [] bajtova) {return BaseEncoding.base16 (). encode (bajtova); } javni bajt [] decodeUsingGuava (niz hexString) {return BaseEncoding.base16 () .decode (hexString.toUpperCase ()); } 

The BaseEncoding kodira i dekodira pomoću zadanih velikih slova. Ako trebamo koristiti mala slova, treba stvoriti novu instancu kodiranja koristeći statičku metodu malim slovima.

8. Zaključak

U ovom smo članku naučili algoritam pretvorbe između bajtnog niza u heksadecimalni Niz. Također smo razgovarali o raznim metodama za kodiranje bajt polja u hex niz i obrnuto.

Ne preporučuje se dodavanje knjižnice da biste koristili samo nekoliko korisnih metoda. Stoga, ako već ne koristimo vanjske knjižnice, trebali bismo koristiti algoritam o kojem smo razgovarali. The DataTypeConverter klasa je još jedan način kodiranja / dekodiranja između različitih vrsta podataka.

Napokon, kompletan izvorni kod ovog vodiča dostupan je na GitHubu.