Convertiți String în Byte Array și Reverse în Java

1. Introducere

În mod frecvent trebuie să facem conversia între matrice de șiruri și octeți în Java. În acest tutorial, vom examina aceste operații în detaliu.

În primul rând, vom analiza diferite moduri de a converti un șir într-o matrice de octeți . Apoi, vom analiza operațiunile similare în sens invers.

2. Conversia șirului în matrice de octeți

Un șir este stocat ca o matrice de caractere Unicode în Java. Pentru a-l converti într-o matrice de octeți , traducem secvența de caractere într-o secvență de octeți. Pentru această traducere, folosim o instanță Charset . Această clasă specifică o mapare între o secvență de char s și o secvență de octet s .

Ne referim la procesul de mai sus drept codificare .

Putem codifica un șir într-o matrice de octeți în Java în mai multe moduri. Să ne uităm la fiecare dintre ele în detaliu cu exemple.

2.1. Utilizarea String.getBytes ()

String Clasa oferă trei supraîncărcate getBytes metode pentru a codifica un șir într - un octet matrice :

  • getBytes () - codifică folosind setul de caractere implicit al platformei
  • getBytes (String charsetName) - codifică folosind setul de caractere numit
  • getBytes (Charset charset) - codifică folosind setul de caractere furnizat

În primul rând, să codificăm un șir folosind setul de caractere implicit al platformei:

String inputString = "Hello World!"; byte[] byteArrray = inputString.getBytes();

Metoda de mai sus depinde de platformă, deoarece folosește setul de caractere implicit al platformei. Putem obține acest set de caractere apelând Charset.defaultCharset () .

În al doilea rând, să codificăm un șir folosind un set de caractere numit:

@Test public void whenGetBytesWithNamedCharset_thenOK() throws UnsupportedEncodingException { String inputString = "Hello World!"; String charsetName = "IBM01140"; byte[] byteArrray = inputString.getBytes("IBM01140"); assertArrayEquals( new byte[] { -56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90 }, byteArrray); }

Această metodă aruncă UnsupportedEncodingException dacă setul de caractere numit nu este acceptat.

Comportamentul celor două versiuni de mai sus este nedefinit dacă intrarea conține caractere care nu sunt acceptate de setul de caractere. În schimb, a treia versiune utilizează matricea de octeți de înlocuire implicită a setului de caractere pentru a codifica intrarea neacceptată.

Apoi, să apelăm a treia versiune a metodei getBytes () și să trecem o instanță a Charset:

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

Aici, folosim metoda din fabrică Charset.forName pentru a obține o instanță a Charset-ului . Această metodă aruncă o excepție de execuție dacă numele setului de caractere solicitat este nevalid. De asemenea, lansează o excepție de rulare dacă setul de caractere este acceptat în JVM curent.

Cu toate acestea, unele seturi de caractere sunt garantate să fie disponibile pe fiecare platformă Java. StandardCharsets Clasa definește constantele pentru aceste tipuri de caractere.

În cele din urmă, să codificăm folosind unul dintre seturile de caractere standard:

@Test public void whenGetBytesWithStandardCharset_thenOK() { String inputString = "Hello World!"; Charset charset = StandardCharsets.UTF_16; byte[] byteArrray = inputString.getBytes(charset); assertArrayEquals( new byte[] { -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); }

Astfel, finalizăm revizuirea diferitelor versiuni getBytes . În continuare, să analizăm metoda furnizată de Charset în sine.

2.2. Utilizarea Charset.encode ()

Charset clasa ofera encode () , o metodă convenabilă care codifica caractere Unicode în octeți. Această metodă înlocuiește întotdeauna caracterele de intrare nevalide și unmappable utilizând matricea de octeți de înlocuire implicită a setului de caractere.

Să folosim metoda de codificare pentru a converti un șir într-o matrice de octeți :

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

După cum putem vedea mai sus, caracterele neacceptate au fost înlocuite cu octetul de înlocuire implicit al setului de caractere 63.

Abordările utilizate până acum utilizează clasa CharsetEncoder intern pentru a efectua codificarea. Să examinăm această clasă în secțiunea următoare.

2.3. CharsetEncoder

CharsetEncoder transformă caracterele Unicode într-o secvență de octeți pentru un set de caractere dat . Mai mult, oferă un control fin asupra procesului de codificare .

Să folosim această clasă pentru a converti un șir într-o matrice de octeți :

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

Aici, creăm o instanță CharsetEncoder apelând metoda newEncoder pe un obiect Charset .

Apoi, suntem specificând acțiunile pentru condițiile de eroare prin apelarea onMalformedInput () și onUnmappableCharacter) ( metode . Putem specifica următoarele acțiuni:

  • IGNORE - renunță la intrarea eronată
  • REPLACE - înlocuiți intrarea eronată
  • RAPORT - raportați eroarea returnând un obiect CoderResult sau aruncând o excepție CharacterCodingException

Mai mult, folosim metoda replaceWith () pentru a specifica matricea de octeți de înlocuire .

Astfel, finalizăm revizuirea diferitelor abordări pentru a converti un șir într-o matrice de octeți. Să vedem în continuare operațiunea inversă.

3. Conversia matricei de octeți în șir

Ne referim la procesul de conversie a unei matrice de octeți într-un șir ca decodare . Similar cu codificarea, acest proces necesită un set de caractere .

Cu toate acestea, nu putem folosi doar niciun set de caractere pentru decodarea unui tablou de octeți. Ar trebui să folosim setul de caractere care a fost folosit pentru a codifica șirul în matricea de octeți .

Putem converti o matrice de octeți într-un șir în mai multe moduri. Să examinăm fiecare dintre ele în detaliu.

3.1. Folosind String Constructor

The String class has few constructors which take a byte array as input. They are all similar to the getBytes method but work in reverse.

First, let's convert a byte array to String using the platform's default charset:

@Test public void whenStringConstructorWithDefaultCharset_thenOK() { byte[] byteArrray = { 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33 }; String string = new String(byteArrray); assertNotNull(string); }

Note that we don't assert anything here about the contents of the decoded string. This is because it may decode to something different, depending on the platform's default charset.

For this reason, we should generally avoid this method.

Secondly, let's use a named charset for decoding:

@Test public void whenStringConstructorWithNamedCharset_thenOK() throws UnsupportedEncodingException { String charsetName = "IBM01140"; byte[] byteArrray = { -56, -123, -109, -109, -106, 64, -26, -106, -103, -109, -124, 90 }; String string = new String(byteArrray, charsetName); assertEquals("Hello World!", string); }

This method throws an exception if the named charset is not available on the JVM.

Thirdly, let's use a Charset object to do decoding:

@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 }; String string = new String(byteArrray, charset); assertEquals("Hello World!", string); }

Finally, let's use a standard Charset for the same:

@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 }; String string = new String(byteArrray, charset); assertEquals("Hello World!", string); }

So far, we have converted a byte array into a String using the constructor. Let's now look into the other approaches.

3.2. Using Charset.decode()

The Charset class provides the decode() method that converts a ByteBuffer to 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; String string = charset.decode(ByteBuffer.wrap(byteArrray)) .toString(); assertEquals("Hello �orl�!", string); }

Here, the invalid input is replaced with the default replacement character for the charset.

3.3. CharsetDecoder

Toate abordările anterioare pentru decodarea internă utilizează clasa CharsetDecoder . Putem folosi această clasă direct pentru controlul cu granulație fină asupra procesului de decodare :

@Test public void whenUsingCharsetDecoder_thenOK() throws CharacterCodingException { byte[] byteArrray = { 72, 101, 108, 108, 111, 32, -10, 111, 114, 108, -63, 33 }; CharsetDecoder decoder = StandardCharsets.US_ASCII.newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .replaceWith("?"); String string = decoder.decode(ByteBuffer.wrap(byteArrray)) .toString(); assertEquals("Hello ?orl?!", string); }

Aici, înlocuim intrările nevalide și caracterele neacceptate cu „?”.

Dacă dorim să fim informați în caz de intrări nevalide, putem schimba decodificatorul astfel:

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

4. Concluzie

În acest articol, am investigat mai multe moduri de a converti șirul într-o matrice de octeți și inversa. Ar trebui să alegem metoda adecvată pe baza datelor de intrare, precum și a nivelului de control necesar pentru intrările nevalide.

Ca de obicei, codul sursă complet poate fi găsit pe GitHub.