Prevod medzi bajtovými poľami a hexadecimálnymi reťazcami v Jave

1. Prehľad

V tomto výučbe sa pozrieme na rôzne spôsoby prevodu bajtového poľa na hexadecimálne Reťazec, a naopak.

Pochopíme tiež konverzný mechanizmus a napíšeme našu implementáciu, aby sme to dosiahli.

2. Konverzia medzi bajtmi a hexadecimálnymi hodnotami

Najskôr sa pozrime na logiku prevodu medzi bajtovými a hexadecimálnymi číslami.

2.1. Byte to Hexadecimal

Bajty sú v Jave 8-bitové celé čísla so znamienkom. Preto musíme konvertujte každý 4-bitový segment na hex zvlášť a zreťazte ich. V dôsledku toho po konverzii dostaneme dva hexadecimálne znaky.

Napríklad môžeme napísať 45 ako binárne 0010 1101 a hexadecimálny ekvivalent bude „2d“:

0010 = 2 (základ 10) = 2 (základ 16) 1101 = 13 (základ 10) = d (základ 16) Preto: 45 = 0010 1101 = 0x2d 

Implementujme túto jednoduchú logiku v Jave:

public String byteToHex (počet bajtov) {char [] hexDigits = nový char [2]; hexDigits [0] = Character.forDigit ((num >> 4) & 0xF, 16); hexDigits [1] = Character.forDigit ((num & 0xF), 16); vrátiť nový reťazec (hexDigits); }

Poďme teda pochopiť vyššie uvedený kód analýzou každej operácie. Najskôr sme vytvorili char pole s dĺžkou 2 na uloženie výstupu:

char [] hexDigits = nový char [2];

Ďalej sme bity vyššieho rádu izolovali posunutím doprava o 4 bity. Potom sme použili masku na izoláciu 4 bitov nižšieho rádu. Maskovanie je povinné, pretože záporné čísla sú interne reprezentované ako dvojkový doplnok kladného čísla:

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

Potom prevedieme zvyšné 4 bity na hexadecimálne:

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

Nakoniec vytvoríme a String objekt z char poľa. A potom vrátil tento objekt ako prevedené hexadecimálne pole.

Teraz pochopme, ako to bude fungovať pre záporný 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 a 0xF = 0000 1100 = 0xc Preto: -4 (základ 10) = 1111 1100 (základ 2) = fc (základ 16)

Je tiež potrebné poznamenať, že Postava.forDigit() metóda vždy vracia malé písmená.

2.2. Hexadecimálne na Byte

Teraz preveďme hexadecimálnu číslicu na bajt. Ako vieme, bajt obsahuje 8 bitov. Preto potrebujeme dve hexadecimálne číslice, aby sme vytvorili jeden bajt.

Najskôr prevedieme každú hexadecimálnu číslicu na binárny ekvivalent osobitne.

A potom musíme zreťaziť dva štyri bitové segmenty, aby sme dostali ekvivalent bytu:

Hexadecimálne: 2d 2 = 0010 (základ 2) d = 1101 (základ 2) Preto: 2d = 0010 1101 (základ 2) = 45

Teraz napíšme operáciu v Jave:

public byte hexToByte (String hexString) {int firstDigit = toDigit (hexString.charAt (0)); int secondDigit = toDigit (hexString.charAt (1)); return (byte) ((firstDigit << 4) + secondDigit); } private int toDigit (char hexChar) {int digit = Character.digit (hexChar, 16); if (digit == -1) {throw new IllegalArgumentException ("Invalid Hexadecimal Character:" + hexChar); } návratná číslica; }

Poďme to pochopiť, jedna operácia po druhej.

Najskôr sme previedli hexadecimálne znaky na celé čísla:

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

Potom sme nechali posunutú najvýznamnejšiu číslicu o 4 bity. V dôsledku toho má binárna reprezentácia nuly na štyroch najmenej významných bitoch.

Potom sme k nej pridali najmenej významnú číslicu:

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

Poďme sa teraz pozrieť na toDigit () metóda úzko. Používame Character.digit () metóda prepočtu. Ak hodnota znaku odovzdaná tejto metóde nie je platná číslica v zadanom radixe, vráti sa -1.

Overujeme návratovú hodnotu a vyvoláme výnimku, ak bola zadaná neplatná hodnota.

3. Prevod medzi bajtovými poliami a hexadecimálnymi Struny

V tejto chvíli vieme, ako previesť bajt na hexadecimálny a naopak. Poďme škálovať tento algoritmus a previesť bajtové pole na / z hexadecimálneho čísla String.

3.1. Byte Array to Hexadecimal String

Musíme sa prehrať cez pole a vygenerovať hexadecimálny pár pre každý bajt:

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

Ako už vieme, na výstupe budú vždy malé písmená.

3.2. Šestnástkový reťazec do bajtového poľa

Najskôr je potrebné skontrolovať, či je dĺžka šestnástkovej sústavy String je párne číslo. Je to preto, že hexadecimálne String s nepárnou dĺžkou bude mať za následok nesprávne znázornenie bajtov.

Teraz iterujeme cez pole a prevedieme každý hexadecimálny pár na bajt:

public byte [] decodeHexString (String hexString) {if (hexString.length ()% 2 == 1) {hodiť novú IllegalArgumentException ("Zadaný neplatný hexadecimálny reťazec."); } bajt [] bajty = nový bajt [hexString.length () / 2]; for (int i = 0; i <hexString.length (); i + = 2) {bytes [i / 2] = hexToByte (hexString.substring (i, i + 2)); } návrat bajtov; }

4. Pomocou BigInteger Trieda

Môžeme vytvoriť objekt typu BigInteger odovzdaním signumového a bajtového poľa.

Teraz môžeme vygenerovať hexadecimálne číslo String pomocou formátu statickej metódy definovaného v String trieda:

public String encodeUsingBigIntegerStringFormat (byte [] bajtov) {BigInteger bigInteger = nový BigInteger (1 bajt); return String.format ("% 0" + (bytes.length << 1) + "x", bigInteger); }

Poskytnutý formát vygeneruje šestnástkové číslo s malými policami a malými policami String. Veľký reťazec môžeme vygenerovať aj tak, že „x“ nahradíme „X“.

Prípadne sme mohli použiť natiahnuť() metóda z BigInteger. Jemný rozdiel v používaní natiahnuť() metóda spočíva v tom, že výstup nie je vyplnený úvodnými nulami:

public String encodeUsingBigIntegerToString (byte [] bajtov) {BigInteger bigInteger = nový BigInteger (1 bajt); return bigInteger.toString (16); }

Poďme sa teraz pozrieť na hexadecimálne číslo String do bajt Konverzia poľa:

public byte [] decodeUsingBigInteger (String hexString) {byte [] byteArray = new BigInteger (hexString, 16) .toByteArray (); if (byteArray [0] == 0) {byte [] výstup = nový bajt [byteArray.length - 1]; System.arraycopy (byteArray, 1, výstup, 0, výstupná dĺžka); spätný výstup; } návrat byteArray; }

The toByteArray () metóda produkuje ďalší znakový bit. Na spracovanie tohto dodatočného bitu sme napísali konkrétny kód.

Preto by sme si mali byť vedomí týchto podrobností pred použitím BigInteger triedy na premenu.

5. Pomocou DataTypeConverter Trieda

The DataTypeConverter triedy je dodávaná s knižnicou JAXB. Toto je súčasť štandardnej knižnice až do Javy 8. Počnúc Javou 9 musíme pridať java.xml.bind modul do runtime výslovne.

Pozrime sa na implementáciu pomocou DataTypeConverter trieda:

public String encodeUsingDataTypeConverter (byte [] bajtov) {návrat DatatypeConverter.printHexBinary (bajty); } verejný bajt [] decodeUsingDataTypeConverter (reťazec hexString) {návrat DatatypeConverter.parseHexBinary (hexString); }

Ako je zobrazené vyššie, jeho použitie je veľmi pohodlné DataTypeConverter trieda. The výstup z printHexBinary () metóda je vždy veľká. Táto trieda dodáva množinu metód tlače a syntaktickej analýzy na konverziu dátových typov.

Pred výberom tohto prístupu sa musíme ubezpečiť, že trieda bude k dispozícii za behu.

6. Používanie knižnice Apache Commons-Codec

Môžeme použiť Hex trieda dodávaná s knižnicou Apache commons-codec:

public String encodeUsingApacheCommons (byte [] bajtov) hodí DecoderException {return Hex.encodeHexString (bajty); } public byte [] decodeUsingApacheCommons (String hexString) hodí DecoderException {return Hex.decodeHex (hexString); }

The výstup z encodeHexString je vždy malými písmenami.

7. Používanie knižnice Guava spoločnosti Google

Poďme sa pozrieť na to, ako BaseEncoding triedy možno použiť na kódovanie a dekódovanie bajtového poľa na hexadecimálne číslo Reťazec:

public String encodeUsingGuava (byte [] bajty) {návrat BaseEncoding.base16 (). encode (bajty); } verejný bajt [] decodeUsingGuava (reťazec hexString) {návrat BaseEncoding.base16 () .decode (hexString.toUpperCase ()); } 

The BaseEncoding štandardne kóduje a dekóduje pomocou veľkých písmen. Ak potrebujeme používať malé písmená, mala by sa nová inštancia kódovania vytvoriť pomocou statickej metódy malými písmenami.

8. Záver

V tomto článku sme sa naučili algoritmus prevodu medzi bajtovým poľom na hexadecimálne String. Diskutovali sme tiež o rôznych metódach kódovania bajtového poľa do hexadecimálneho reťazca a naopak.

Neodporúča sa pridávať knižnicu iba na použitie niekoľkých metód obslužných programov. Preto, ak externé knižnice už nepoužívame, mali by sme použiť diskutovaný algoritmus. The DataTypeConverter trieda je ďalší spôsob kódovania / dekódovania medzi rôznymi dátovými typmi.

Nakoniec je kompletný zdrojový kód tohto tutoriálu k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found