Convertir une chaîne en tableau d’octets et l’inverser en Java

Convertir une chaîne en tableau d'octets et inverser en Java

1. introduction

Nous avons souvent besoin de convertir entre les tableauxString etbyte en Java. Dans ce didacticiel, nous examinerons ces opérations en détail.

Tout d'abord, nous allons examiner différentes manières de convertir unString en un tableaubyte. Ensuite, nous examinerons des opérations similaires en sens inverse.

2. Conversion deString en tableauByte

UnString est stocké sous forme de tableau de caractères Unicode en Java. Pour le convertir en un tableaubyte, nous traduisons la séquence de caractères en une séquence d'octets. Pour cette traduction,we use an instance of Charset. This class specifies a mapping between a sequence of chars and a sequence of bytes.

Nous appelons le processus ci-dessusencoding.

Nous pouvons encoder unString dans un tableaubyte en Java de plusieurs manières. Examinons chacun d'eux en détail avec des exemples.

2.1. Utilisation deString.getBytes()

The String class provides three overloaded getBytes methods to encode a String into a byte array:

Premièrement,let’s encode a string using the platform’s default charset:

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

La méthode ci-dessus dépend de la plate-forme car elle utilise le jeu de caractères par défaut de la plate-forme. Nous pouvons obtenir ce jeu de caractères en appelantCharset.defaultCharset().

Deuxièmement,let’s encode a string using a named charset:

@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);
}

Cette méthode renvoieUnsupportedEncodingException si le jeu de caractères nommé n'est pas pris en charge.

Le comportement des deux versions ci-dessus n'est pas défini si l'entrée contient des caractères qui ne sont pas pris en charge par le jeu de caractères. En revanche, la troisième version utilise le tableau d'octets de remplacement par défaut du jeu de caractères pour coder les entrées non prises en charge.

Ensuite,let’s call the third version of the getBytes() method and pass an instance of 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);
}

Ici, nous utilisons la méthode d'usineCharset.forName pour obtenir une instance desCharset. Cette méthode lève une exception d'exécution si le nom du jeu de caractères demandé n'est pas valide. Il lève également une exception d'exécution si le jeu de caractères est pris en charge dans la JVM actuelle.

Cependant, il est garanti que certains jeux de caractères sont disponibles sur toutes les plateformes Java. La classeStandardCharsets définit des constantes pour ces jeux de caractères.

Enfin,let’s encode using one of the standard charsets:

@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);
}

Ainsi, nous terminons la revue des différentes versions degetBytes. Ensuite, examinons la méthode fournie parCharset lui-même.

2.2. Utilisation deCharset.encode()

The Charset class provides encode(), a convenient method that encodes Unicode characters into bytes. Cette méthode remplace toujours les entrées non valides et les caractères non mappables en utilisant le tableau d'octets de remplacement par défaut du jeu de caractères.

Utilisons la méthodeencode pour convertir unString en un tableaubyte:

@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);
}

Comme nous pouvons le voir ci-dessus, les caractères non pris en charge ont été remplacés par le remplacement par défaut du jeu de caractèresbyte 63.

Les approches utilisées jusqu'à présent utilisent la classeCharsetEncoder en interne pour effectuer le codage. Examinons cette classe dans la section suivante.

2.3. CharsetEncoder

CharsetEncoder transforms Unicode characters into a sequence of bytes for a given charset. Moreover, it provides fine-grained control over the encoding process.

Utilisons cette classe pour convertir unString en un tableaubyte:

@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);
}

Ici, nous créons une instance deCharsetEncoder en appelant la méthodenewEncoder ur un objetCharset.

Ensuite, nous spécifions des actions pour les conditions d'erreur en appelant les méthodesonMalformedInput() etonUnmappableCharacter()  Nous pouvons spécifier les actions suivantes:

  • IGNORE - supprime l'entrée erronée

  • REPLACE - remplace l'entrée erronée

  • RAPPORT - signale l'erreur en renvoyant un objetCoderResult ou en lançant unCharacterCodingException

De plus, nous utilisons la méthodereplaceWith() pour spécifier le tableau de remplacementbyte.

Ainsi, nous terminons la révision de diverses approches pour convertir une chaîne en un tableau d'octets. Voyons maintenant l’opération inverse.

3. Conversion de tableau d'octets en chaîne

We refer to the process of converting a byte array to a String as decoding. Semblable au codage, ce processus nécessite unCharset.

Cependant, nous ne pouvons utiliser aucun jeu de caractères pour décoder un tableau d'octets. We should use the charset that was used to encode the String into the byte array.

Nous pouvons convertir un tableau d'octets en chaîne de plusieurs manières. Examinons chacun d’eux en détail.

3.1. Utilisation du constructeurString

The String class has few constructors which take a byte array as input. Ils sont tous similaires à la méthodegetBytes mais fonctionnent en sens inverse.

Premièrement,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);
}

Notez que nous n’affirmons rien ici sur le contenu de la chaîne décodée. En effet, il peut décoder en quelque chose de différent, selon le jeu de caractères par défaut de la plate-forme.

Pour cette raison, nous devrions généralement éviter cette méthode.

Deuxièmement,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);
}

Cette méthode lève une exception si le jeu de caractères nommé n'est pas disponible sur la machine virtuelle Java.

Troisièmement,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);
}

Enfin,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);
}

Jusqu'à présent, nous avons converti un tableaubyte en unString en utilisant le constructeur. Voyons maintenant les autres approches.

3.2. Utilisation deCharset.decode()

La classeCharset fournit la méthodedecode() qui convertit unByteBuffer enString:

@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);
}

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

3.3. CharsetDecoder

Toutes les approches de décodage précédentes utilisent en interne la classeCharsetDecoder. We can use this class directly for fine-grained control on the decoding process:

@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);
}

Ici, nous remplaçons les entrées non valides et les caractères non pris en charge par «?».

Si nous voulons être informés en cas d'entrées invalides, nous pouvons changer lesdecoder comme:

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

4. Conclusion

Dans cet article, nous avons étudié plusieurs façons de convertirString en un tableau d'octets et inverser. Nous devrions choisir la méthode appropriée en fonction des données d'entrée ainsi que du niveau de contrôle requis pour les entrées non valides.

Comme d'habitude, le code source complet peut être trouvéover on GitHub.