Bájt tömbök és hexadecimális karakterláncok közötti konvertálás a Java-ban

1. Áttekintés

Ebben az oktatóanyagban megvizsgáljuk a bájt tömb hexadecimálissá alakításának különböző módjait Húr, és fordítva.

Megértjük a konverziós mechanizmust és meg fogjuk írni a megvalósításunkat ennek elérése érdekében.

2. Konvertálás bájt és hexadecimális között

Először vessünk egy pillantást a bájt és a hexadecimális számok közötti konverziós logikára.

2.1. Bájttól hexadecimálisig

A bájtok 8 bites előjelű egész számok a Java-ban. Ezért kell mindegyik 4 bites szegmenst külön-külön hexává konvertálja és összefűzi. Következésképpen az átalakítás után két hexadecimális karaktert kapunk.

Például a 45-et 0010 1101-nek írhatjuk bináris formában, és a hexadecimális egyenérték „2d” lesz:

0010 = 2 (10. alap) = 2 (16. alap) 1101 = 13 (10. alap) = d (16. alap) Ezért: 45 = 0010 1101 = 0x2d 

Vezessük be ezt az egyszerű logikát a Java-ban:

public String byteToHex (bájt száma) {char [] hexDigits = új char [2]; hexDigits [0] = Character.forDigit ((szám >> 4) & 0xF, 16); hexDigits [1] = Character.forDigit ((szám & 0xF), 16); return new String (hexDigits); }

Most értsük meg a fenti kódot az egyes műveletek elemzésével. Először is létrehoztunk egy 2 hosszúságú char tömböt a kimenet tárolására:

char [] hexDigits = új char [2];

Ezután magasabb rendű biteket izoláltunk 4 bit jobbra tolásával. Ezután maszkot alkalmaztunk az alacsonyabb rendű 4 bit elkülönítésére. A maszkolásra azért van szükség, mert a negatív számok belsőleg képviselik a pozitív szám kettő kiegészítését:

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

Ezután a fennmaradó 4 bitet hexadecimálissá konvertáljuk:

hexDigits [1] = Character.forDigit ((szám & 0xF), 16);

Végül létrehozunk egy Húr objektum a char tömbből. Ezután visszaadta ezt az objektumot konvertált hexadecimális tömbként.

Most pedig értsük meg, hogyan fog működni ez egy negatív bájt -4 esetén:

hexDigits [0]: 1111 1100 >> 4 = 1111 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 Ezért: -4 (10. alap) = 1111 1100 (2. alap) = fc (16. alap)

Azt is érdemes megjegyezni, hogy a Karakter.forDigit() A metódus mindig kisbetűket ad vissza.

2.2. Hexadecimális bájtig

Most konvertáljuk a hexadecimális számjegyet bájttá. Mint tudjuk, egy bájt 8 bitet tartalmaz. Ebből kifolyólag, egy bájt létrehozásához két hexadecimális számjegyre van szükségünk.

Először minden hexadecimális számjegyet külön alakítunk át bináris egyenértékre.

Ezután össze kell összefűznünk a két négy bites szegmenst, hogy megkapjuk a bájtegyenértéket:

Hexadecimális: 2d 2 = 0010 (2. alap) d = 1101 (2. alap) Ezért: 2d = 0010 1101 (2. alap) = 45

Most írjuk meg a műveletet Java-ban:

public byte hexToByte (String hexString) {int firstDigit = toDigit (hexString.charAt (0)); int secondDigit = toDigit (hexString.charAt (1)); return (byte) ((elsőDigit << 4) + másodikDigit); } private int toDigit (char hexChar) {int digit = Karakter.digit (hexChar, 16); if (digit == -1) {dobjon új IllegalArgumentException ("Érvénytelen hexadecimális karakter:" + hexChar); } visszatérő számjegy; }

Értsük meg ezt, egy-egy műveletet.

Mindenekelőtt a hexadecimális karaktereket egész számokká alakítottuk át:

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

Ezután a legjelentősebb számjegyet eltoltuk 4 bittel. Következésképpen a bináris ábrázolásnak négy legkevésbé jelentős bitje van.

Ezután hozzáadtuk a legkevésbé jelentős számjegyet:

return (byte) ((elsőDigit << 4) + másodikDigit);

Most vizsgáljuk meg a toDigit () módszer szorosan. A Karakter.digit () módszer az átalakításra. Ha az erre a módszerre továbbított karakterérték nem érvényes számjegy a megadott tartományban, akkor a -1 érték jelenik meg.

Érvényesítjük a visszatérési értéket és kivételt vetünk, ha érvénytelen értéket adtunk át.

3. Konvertálás a bájt tömbök és a hexadecimális között Húrok

Ezen a ponton tudjuk, hogyan lehet egy bájtot hexadecimálissá konvertálni, és fordítva. Méretezzük ezt az algoritmust, és konvertáljuk a bájtömböt hexadecimális értékre / számra Húr.

3.1. Bájtömb hexadecimálisra Húr

Végig kell lépnünk a tömbön, és minden bájthoz hexadecimális párokat kell létrehoznunk:

public String encodeHexString (byte [] byteArray) {StringBuffer hexStringBuffer = új StringBuffer (); for (int i = 0; i <byteArray.length; i ++) {hexStringBuffer.append (byteToHex (byteArray [i])); } return hexStringBuffer.toString (); }

Mint már tudjuk, a kimenet mindig kisbetűs lesz.

3.2. Hexadecimális karakterlánc-byte tömb

Először meg kell vizsgálnunk, hogy a hexadecimális hossza megvan-e Húr páros szám. Ez azért van, mert egy hexadecimális Húr páratlan hosszúsággal helytelen bájt ábrázolást eredményez.

Most iteráljuk a tömböt, és minden hexadecimális párt átalakítunk bájttá:

public byte [] decodeHexString (String hexString) {if (hexString.length ()% 2 == 1) {dobjon új IllegalArgumentException-t ("Érvénytelen hexadecimális karakterláncot tartalmaz."); } bájt [] bájt = új bájt [hexString.length () / 2]; for (int i = 0; i <hexString.length (); i + = 2) {byte [i / 2] = hexToByte (hexString.substring (i, i + 2)); } visszatérési bájtok; }

4. A BigInteger Osztály

Tudunk típusú objektum létrehozása BigInteger aláírás és bájt tömb átadásával.

Most előállíthatjuk a hexadecimális értéket Húr alatt definiált statikus módszerformátum segítségével Húr osztály:

public String encodeUsingBigIntegerStringFormat (byte [] byte) {BigInteger bigInteger = új BigInteger (1, bájt); return String.format ("% 0" + (bájtok.hossz << 1) + "x", bigInteger); }

A megadott formátum nulla betétű kisbetűket generál Húr. Nagybetűs karakterláncot is létrehozhatunk, ha az „x” -et „X” -re cseréljük.

Alternatív megoldásként használhatnánk a toString () módszer től BigInteger. A finom különbség a toString () A módszer az, hogy a kimenet nincs kitöltve vezető nullákkal:

public String encodeUsingBigIntegerToString (byte [] byte) {BigInteger bigInteger = új BigInteger (1, bájt); return bigInteger.toString (16); }

Most vessünk egy pillantást a hexadecimálisra Húr nak nek byte Tömb konverzió:

public byte [] decodeUsingBigInteger (String hexString) {byte [] byteArray = new BigInteger (hexString, 16) .toByteArray (); if (byteArray [0] == 0) {byte [] output = új byte [byteArray.length - 1]; System.arraycopy (byteArray, 1, output, 0, output.length); visszatérő kimenet; } return byteArray; }

A toByteArray () metódus további előjel bitet állít elő. Külön kódot írtunk ennek a további bitnek a kezelésére.

Ennélfogva tudnunk kell ezeket a részleteket, mielőtt a BigInteger osztály az átalakításhoz.

5. A DataTypeConverter Osztály

A DataTypeConverter osztály JAXB könyvtárral van ellátva. Ez a Java 8-ig terjedő standard könyvtár része. A Java 9-től kezdve hozzá kell adnunk java.xml.bind modult a futásidőhöz kifejezetten.

Vessünk egy pillantást a megvalósításra a DataTypeConverter osztály:

public String encodeUsingDataTypeConverter (byte [] byte) {return DatatypeConverter.printHexBinary (byte); } public byte [] decodeUsingDataTypeConverter (String hexString) {return DatatypeConverter.parseHexBinary (hexString); }

Amint fent látható, nagyon kényelmes használni DataTypeConverter osztály. A kimenete printHexBinary () módszer mindig nagybetűvel van. Ez az osztály nyomtatási és elemzési módszereket kínál az adattípus-átalakításhoz.

Mielőtt ezt a megközelítést választanánk, meg kell győződnünk arról, hogy az osztály futás közben elérhető lesz-e.

6. Az Apache Commons-Codec Library használata

Használhatjuk a Hex osztály az Apache commons-codec könyvtárral szállítva:

public String encodeUsingApacheCommons (byte [] byte) dobja a DecoderException {return Hex.encodeHexString (byte); } public byte [] decodeUsingApacheCommons (String hexString) dobja a DecoderException {return Hex.decodeHex (hexString); }

A kimenete encodeHexString mindig kisbetûs.

7. A Google Guava könyvtárának használata

Vessünk egy pillantást arra, hogyan BaseEncoding osztály használható a bájt tömb kódolására és dekódolására a hexadecimális értékig Húr:

public String encodeUsingGuava (byte [] byte) {return BaseEncoding.base16 (). encode (byte); } public byte [] decodeUsingGuava (String hexString) {return BaseEncoding.base16 () .decode (hexString.toUpperCase ()); } 

A BaseEncoding alapértelmezés szerint nagybetűk használatával kódol és dekódol. Ha kisbetűket kell használnunk, új kódolási példányt kell létrehozni a statikus metódus kisbetűivel.

8. Következtetés

Ebben a cikkben megtanultuk a bájt tömb hexadecimális közötti konverziós algoritmusát Húr. Megvitattuk a bájt tömb hex sztringbe történő kódolásának különféle módszereit is és fordítva.

Nem ajánlott könyvtárat hozzáadni csak néhány segédprogram használatához. Ezért, ha még nem használjuk a külső könyvtárakat, akkor a tárgyalt algoritmust kell használnunk. A DataTypeConverter osztály egy másik módja a különféle adattípusok közötti kódolásnak / dekódolásnak.

Végül az oktatóanyag teljes forráskódja elérhető a GitHubon.