Preveďte reťazec na bajtové pole a reverzné v Jave

1. Úvod

Často musíme prevádzať konverzie String a bajt pole v Jave. V tomto výučbe podrobne preskúmame tieto operácie.

Najskôr sa pozrieme na rôzne spôsoby prevodu a String do a bajt pole. Potom sa pozrieme na podobné operácie opačne.

2. Konvertovanie String do Byte Pole

A String je uložený ako pole znakov Unicode v Jave. Ak ho chcete previesť na a bajt pole, preložíme postupnosť Znakov do postupnosti bajtov. Pre tento preklad použijeme inštanciu Charset. Táto trieda určuje mapovanie medzi postupnosťou chars a postupnosť bajts.

Vyššie uvedený proces označujeme ako kódovanie.

Môžeme zakódovať a String do a bajt pole v Jave viacerými spôsobmi. Pozrime sa na každú z nich podrobne s príkladmi.

2.1. Použitím String.getBytes ()

The String triedy poskytuje tri preťažené getBytes metódy na kódovanie a String do bajt pole:

  • getBytes () - kóduje pomocou predvolenej znakovej sady platformy
  • getBytes (reťazec charsetName) - kóduje pomocou pomenovanej znakovej sady
  • getBytes (znaková sada Charset) - kóduje pomocou poskytnutej znakovej sady

Po prvé, poďme kódovať reťazec pomocou predvolenej znakovej sady platformy:

Reťazec inputString = "Hello World!"; byte [] byteArrray = inputString.getBytes ();

Vyššie uvedená metóda je závislá od platformy, pretože používa predvolenú znakovú sadu platformy. Túto znakovú sadu môžeme získať volaním Charset.defaultCharset ().

Po druhé, poďme kódovať reťazec pomocou pomenovanej znakovej sady:

@Test public void whenGetBytesWithNamedCharset_thenOK () vyvolá UnsupportedEncodingException {String inputString = "Hello World!"; Reťazec charsetName = "IBM01140"; byte [] byteArrray = inputString.getBytes ("IBM01140"); assertArrayEquals (nový bajt [] {-56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90}, byteArrray); }

Táto metóda hodí UnsupportedEncodingException ak pomenovaná znaková sada nie je podporovaná.

Správanie vyššie uvedených dvoch verzií nie je definované, ak vstup obsahuje znaky, ktoré znaková sada nepodporuje. Naproti tomu tretia verzia používa na kódovanie nepodporovaného vstupu predvolené náhradné bajtové pole charsetu.

Ďalšie, nazvime tretiu verziu getBytes () metóda a odovzdať inštanciu Znaková sada:

@Test public void whenGetBytesWithCharset_thenOK () {String inputString = "Hello ਸੰਸਾਰ!"; Charset charset = Charset.forName ("ASCII"); byte [] byteArrray = inputString.getBytes (charset); assertArrayEquals (nový bajt [] {72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33}, byteArrray); }

Tu používame továrenskú metódu Charset.forName získať inštanciu Charset. Táto metóda vyvolá výnimku za behu, ak je názov požadovanej znakovej sady neplatný. Taktiež vyvolá runtime výnimku, ak je znaková sada podporovaná v aktuálnom JVM.

Niektoré znakové sady sú však zaručene dostupné na každej platforme Java. The ŠtandardnéCharzety trieda definuje konštanty pre tieto znakové sady.

Nakoniec poďme kódovať pomocou jednej zo štandardných charsetov:

@Test public void whenGetBytesWithStandardCharset_thenOK () {String inputString = "Hello World!"; Charset charset = StandardCharsets.UTF_16; byte [] byteArrray = inputString.getBytes (charset); assertArrayEquals (nový bajt [] {-2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0 , 108, 0, 100, 0, 33}, byteArrray); }

Dokončujeme teda prehľad rôznych getBytes verzie. Ďalej sa pozrime na metódu, ktorú poskytuje Charset sám.

2.2. Použitím Charset.encode ()

The Charset trieda poskytuje kódovať (), pohodlná metóda, ktorá kóduje znaky Unicode do bajtov. Táto metóda vždy nahradí neplatný vstup a nezmazateľné znaky pomocou predvoleného náhradného bajtového poľa charsetu.

Použime zakódovať metóda prevodu a String do a bajt pole:

@Test public void whenEncodeWithCharset_thenOK () {String inputString = "Dobrý deň ਸੰਸਾਰ!"; Charset charset = StandardCharsets.US_ASCII; byte [] byteArrray = charset.encode (inputString) .array (); assertArrayEquals (nový bajt [] {72, 101, 108, 108, 111, 32, 63, 63, 63, 63, 63, 33}, byteArrray); }

Ako vidíme vyššie, nepodporované znaky boli nahradené predvolenou náhradou znakovej sady bajt 63.

Doteraz používané prístupy využívajú CharsetEncoder triedy interne vykonávať kódovanie. Pozrime sa na túto triedu v nasledujúcej časti.

2.3. CharsetEncoder

CharsetEncoder transformuje znaky Unicode na postupnosť bajtov pre danú znakovú sadu. Okrem toho poskytuje jemnozrnnú kontrolu nad procesom kódovania.

Použime túto triedu na prevod a String do a bajt pole:

@ Test public void whenUsingCharsetEncoder_thenOK () hodí CharacterCodingException {String inputString = "Hello ਸੰਸਾਰ!"; Kodér CharsetEncoder = StandardCharsets.US_ASCII.newEncoder (); encoder.onMalformedInput (CodingErrorAction.IGNORE) .onUnmappableCharacter (CodingErrorAction.REPLACE) .replaceWith (nový bajt [] {0}); byte [] byteArrray = encoder.encode (CharBuffer.wrap (inputString)) .array (); assertArrayEquals (nový bajt [] {72, 101, 108, 108, 111, 32, 0, 0, 0, 0, 0, 33}, byteArrray); }

Tu vytvárame inštanciu CharsetEncoder zavolaním na newEncoder metóda na a Charset objekt.

Potom špecifikujeme akcie pre chybové podmienky volaním súboru onMalformedInput () a onUnmappableCharacter () metódy. Môžeme určiť nasledujúce akcie:

  • Ignorovať - ​​zrušte chybný vstup
  • VYMENIŤ - nahradiť chybný vstup
  • SPRÁVA - nahláste chybu vrátením a CoderResult predmet alebo hádzanie a CharacterCodingException

Ďalej používame nahradiť s() spôsob určenia náhrady bajt pole.

Dokončujeme teda prehľad rôznych prístupov k prevedeniu reťazca String na bajtové pole. Pozrime sa ďalej na reverznú operáciu.

3. Prevod bajtového poľa na reťazec

Odvolávame sa na proces premeny a bajt pole do a String ako dekódovanie. Podobne ako pri kódovaní, aj tento proces vyžaduje Charset.

Na dekódovanie bajtového poľa však nemôžeme použiť iba ľubovoľnú znakovú sadu. Mali by sme použiť znakovú sadu, ktorá bola použitá na kódovanie súboru String do bajt pole.

Bajtové pole môžeme previesť na String mnohými spôsobmi. Poďme každý z nich podrobne preskúmať.

3.1. Pomocou String Konštruktér

The String trieda má niekoľko konštruktorov, ktoré berú a bajt pole ako vstup. Všetky sú podobné getBytes metódou, ale obráťte sa.

Najprv, poďme previesť bajtové pole na String pomocou predvolenej znakovej sady platformy:

@Test public void whenStringConstructorWithDefaultCharset_thenOK () {byte [] byteArrray = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}; Reťazcový reťazec = nový Reťazec (byteArrray); assertNotNull (reťazec); }

Upozorňujeme, že tu nebudeme tvrdiť nič o obsahu dekódovaného reťazca. Je to preto, lebo sa môže dekódovať na niečo iné, v závislosti od predvolenej znakovej sady platformy.

Z tohto dôvodu by sme sa mali tejto metóde všeobecne vyhnúť.

Po druhé, použijeme na dekódovanie pomenovanú znakovú sadu:

@ Test public void whenStringConstructorWithNamedCharset_thenOK () vyvolá UnsupportedEncodingException {String charsetName = "IBM01140"; byte [] byteArrray = {-56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90}; Reťazcový reťazec = nový Reťazec (byteArrray, charsetName); assertEquals ("Hello World!", reťazec); }

Táto metóda vyvolá výnimku, ak pomenovaná znaková sada nie je k dispozícii na JVM.

Po tretie, použijeme a Charset objekt urobiť dekódovanie:

@Test public void whenStringConstructorWithCharSet_thenOK () {Charset charset = Charset.forName ("UTF-8"); byte [] byteArrray = {72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33}; Reťazcový reťazec = nový Reťazec (byteArrray, charset); assertEquals ("Hello World!", reťazec); }

Nakoniec použijeme štandard Charset pre to isté:

@Test public void whenStringConstructorWithStandardCharSet_thenOK () {Charset charset = StandardCharsets.UTF_16; byte [] byteArrray = {-2, -1, 0, 72, 0, 101, 0, 108, 0, 108, 0, 111, 0, 32, 0, 87, 0, 111, 0, 114, 0, 108, 0, 100, 0, 33}; Reťazcový reťazec = nový Reťazec (byteArrray, charset); assertEquals ("Hello World!", reťazec); }

Doteraz sme premenili a bajt pole do a String pomocou konštruktora. Pozrime sa teraz na ďalšie prístupy.

3.2. Použitím Charset.decode ()

The Charset trieda poskytuje dekódovať () metóda, ktorá prevádza a ByteBuffer do String:

@Test public void whenDecodeWithCharset_thenOK () {byte [] byteArrray = {72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33}; Charset charset = StandardCharsets.US_ASCII; Reťazcový reťazec = charset.decode (ByteBuffer.wrap (byteArrray)) .toString (); assertEquals ("Hello  orl !", string); }

Tu, neplatný vstup sa nahradí predvoleným znakom nahradenia znakovej sady.

3.3. CharsetDecoder

Všetky predchádzajúce prístupy k internému dekódovaniu používajú CharsetDecoder trieda. Túto triedu môžeme použiť priamo na jemnozrnné riadenie procesu dekódovania:

@Test public void whenUsingCharsetDecoder_thenOK () hodí CharacterCodingException {byte [] byteArrray = {72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33}; Dekodér CharsetDecoder = StandardCharsets.US_ASCII.newDecoder (); decoder.onMalformedInput (CodingErrorAction.REPLACE) .onUnmappableCharacter (CodingErrorAction.REPLACE) .replaceWith ("?"); Reťazcový reťazec = decoder.decode (ByteBuffer.wrap (byteArrray)) .toString (); assertEquals ("Ahoj? orl ?!", reťazec); }

Tu nahradzujeme neplatné vstupy a nepodporované znaky znakom „?“.

Ak chceme byť informovaní v prípade neplatných vstupov, môžeme zmeniť dekodér ako:

decoder.onMalformedInput (CodingErrorAction.REPORT) .onUnmappableCharacter (CodingErrorAction.REPORT)

4. Záver

V tomto článku sme skúmali niekoľko spôsobov konverzie String na bajtové pole a obrátiť. Mali by sme zvoliť vhodnú metódu založenú na vstupných údajoch, ako aj na úrovni kontroly potrebnej pre neplatné vstupy.

Celý zdrojový kód nájdete ako obvykle na GitHub.