Converter String em matriz de bytes e reverter em Java
1. Introdução
Freqüentemente, precisamos converter entre o arrayString ebyte em Java. Neste tutorial, examinaremos essas operações em detalhes.
Primeiro, veremos várias maneiras de converter uma matrizString em uma matrizbyte. Em seguida, veremos operações semelhantes ao contrário.
2. ConvertendoString em matrizByte
UmString é armazenado como uma matriz de caracteres Unicode em Java. Para convertê-lo em um arraybyte, traduzimos a sequência de caracteres em uma sequência de bytes. Para esta tradução,we use an instance of Charset. This class specifies a mapping between a sequence of chars and a sequence of bytes.
Nos referimos ao processo acima comoencoding.
Podemos codificar umString em um arraybyte em Java de várias maneiras. Vejamos cada um deles em detalhes com exemplos.
2.1. UsandoString.getBytes()
The String class provides three overloaded getBytes methods to encode a String into a byte array:
-
getBytes() - codifica usando o conjunto de caracteres padrão da plataforma
-
getBytes (String charsetName) - codifica usando o charset nomeado
-
getBytes (Charset charset) - codifica usando o conjunto de caracteres fornecido
Em primeiro lugar,let’s encode a string using the platform’s default charset:
String inputString = "Hello World!";
byte[] byteArrray = inputString.getBytes();
O método acima é dependente da plataforma, pois usa o conjunto de caracteres padrão da plataforma. Podemos obter esse conjunto de caracteres chamandoCharset.defaultCharset().
Em segundo lugar,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);
}
Este método lançaUnsupportedEncodingException se o charset nomeado não for suportado.
O comportamento das duas versões acima é indefinido se a entrada contiver caracteres que não são suportados pelo conjunto de caracteres. Em contraste, a terceira versão usa a matriz de bytes de substituição padrão do conjunto de caracteres para codificar a entrada não suportada.
A seguir,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);
}
Aqui, estamos usando o método de fábricaCharset.forName para obter uma instância deCharset. Este método lança uma exceção de tempo de execução se o nome do conjunto de caracteres solicitado for inválido. Ele também lança uma exceção de tempo de execução se o conjunto de caracteres for suportado na JVM atual.
No entanto, é garantido que alguns charsets estejam disponíveis em todas as plataformas Java. A classeStandardCharsets define constantes para esses conjuntos de caracteres.
Finalmente,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);
}
Assim, concluímos a revisão das várias versões degetBytes. A seguir, vamos examinar o método fornecido pelo próprioCharset.
2.2. UsandoCharset.encode()
The Charset class provides encode(), a convenient method that encodes Unicode characters into bytes. Este método sempre substitui a entrada inválida e os caracteres não mapeáveis usando a matriz de bytes de substituição padrão do conjunto de caracteres.
Vamos usar o métodoencode para converter umString em uma matrizbyte:
@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);
}
Como podemos ver acima, os caracteres não suportados foram substituídos pela substituição padrão do conjunto de caracteresbyte 63.
As abordagens usadas até agora usam a classeCharsetEncoder internamente para realizar a codificação. Vamos examinar essa classe na próxima seção.
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.
Vamos usar esta classe para converter umString em uma matrizbyte:
@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);
}
Aqui, estamos criando uma instância deCharsetEncoder chamando o métodonewEncoder em um objetoCharset.
Então, estamos especificando ações para condições de erro chamando os métodosonMalformedInput()eonUnmappableCharacter() . . Podemos especificar as seguintes ações:
-
IGNORE - solta a entrada incorreta
-
REPLACE - substitua a entrada incorreta
-
RELATÓRIO - relatar o erro retornando um objetoCoderResult ou jogando umCharacterCodingException
Além disso, estamos usando o métodoreplaceWith() para especificar o array de substituiçãobyte.
Assim, concluímos a revisão de várias abordagens para converter uma String em uma matriz de bytes. Vejamos a seguir a operação reversa.
3. Convertendo matriz de bytes em string
We refer to the process of converting a byte array to a String as decoding. Semelhante à codificação, este processo requer umCharset.
No entanto, não podemos apenas usar qualquer conjunto de caracteres para decodificar uma matriz de bytes. We should use the charset that was used to encode the String into the byte array.
Podemos converter uma matriz de bytes em uma String de várias maneiras. Vamos examinar cada um deles em detalhes.
3.1. Usando o construtorString
The String class has few constructors which take a byte array as input. Eles são todos semelhantes ao métodogetBytes, mas funcionam ao contrário.
Primeiro,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);
}
Observe que não afirmamos nada aqui sobre o conteúdo da string decodificada. Isso ocorre porque ele pode decodificar para algo diferente, dependendo do conjunto de caracteres padrão da plataforma.
Por esse motivo, geralmente devemos evitar esse método.
Em segundo lugar,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);
}
Este método lança uma exceção se o charset nomeado não estiver disponível na JVM.
Em terceiro lugar,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);
}
Finalmente,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);
}
Até agora, convertemos uma matrizbyte emString usando o construtor. Vamos agora examinar as outras abordagens.
3.2. UsandoCharset.decode()
A classeCharset fornece o métododecode() que converte aByteBuffer emString:
@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);
}
Aqui,the invalid input is replaced with the default replacement character for the charset.
3.3. CharsetDecoder
Todas as abordagens anteriores para decodificação interna usam a 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);
}
Aqui, estamos substituindo entradas inválidas e caracteres não suportados por "?".
Se quisermos ser informados no caso de entradas inválidas, podemos alterar odecoder como:
decoder.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT)
4. Conclusão
Neste artigo, investigamos várias maneiras de converterString em uma matriz de bytes e reverter. Devemos escolher o método apropriado com base nos dados de entrada, bem como no nível de controle necessário para entradas inválidas.
Como de costume, o código-fonte completo pode ser encontradoover on GitHub.