Рубрики
Без рубрики

Преобразование строки в byte Array и обратный в Java

Если вы посмотрите на способы преобразования между строкой и массивом карт в Java

Автор оригинала: Chandra Prakash.

Преобразование строки в byte Array и обратный в Java

1. Введение

Нам часто нужно конвертировать между Струнные и byte массива в Java. В этом учебнике мы рассмотрим эти операции в деталях.

Дальнейшее чтение:

Java InputStream в Byte Array и ByteBuffer

Java – Читатель в Byte Array

Java Byte Array для вводапотока

Во-первых, мы будем смотреть на различные способы преобразования Струнные к byte массив. Затем мы посмотрим на аналогичные операции в обратном направлении.

2. Преобразование строки в Byte Array

Струнные хранится в качестве массива символов Unicode на Java. Чтобы преобразовать его в byte массив, мы переводим последовательность символов в последовательность байтов. Для этого перевода, мы используем пример Чарсет . Этот класс определяет отображение между последовательностью char s и последовательность byte s .

Мы называем вышеупомянутый процесс кодирование .

Мы можем закодировать Струнные в byte массива в Java несколькими способами. Рассмотрим каждый из них подробно с примерами.

2.1. Использование String.getBytes()

Струнные класс обеспечивает три перегруженных getBytes методы кодирования Струнные в карт- массив :

Во-первых, давайте закодируем строку с помощью charset платформы по умолчанию:

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

Вышеупомянутый метод зависит от платформы, поскольку он использует charset платформы по умолчанию. Мы можем получить этот charset, позвонив Charset.defaultCharset () .

Во-вторых, давайте закодируем строку с помощью имени 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);
}

Этот метод бросает НеподдерживаемыйУкодированиеИсключаемость если названный charset не поддерживается.

Поведение вышеуказанных двух версий не определено, если вход содержит символы, которые не поддерживаются charset. В отличие от этого, третья версия использует набор замены charset по умолчанию для кодирования неподдерживаемого ввода.

Далее, назовем третью версию getBytes () метод и пройти экземпляр Чарсет:

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

Здесь мы используем заводской метод Charset.forName чтобы получить экземпляр Чарсет . Этот метод делает исключение времени выполнения, если имя запрошенного charset является недействительным. Он также бросает исключение времени выполнения, если charset поддерживается в текущем JVM.

Тем не менее, некоторые charsets гарантированно будут доступны на каждой платформе Java. СтандартныеЧарсеты класс определяет константы для этих charsets.

Наконец, давайте закодируем с помощью одного из стандартных 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);
}

Таким образом, мы заверим обзор различных getBytes Версии. Далее рассмотрим метод, предоставленный Чарсет себя.

2.2. Использование Charset.encode()

Чарсет класс обеспечивает кодировать () , удобный метод, который кодирует символы Unicode в байты. Этот метод всегда заменяет недействительные входные и неприменимые символы с помощью массива byte замены charset по умолчанию.

Давайте использовать кодировать метод преобразования струна в байт массив:

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

Как мы видим выше, неподдерживаемые символы были заменены заменой charset по умолчанию byte 63.

Используемые до сих пор подходы используют ЧарсетЭнкодер класс внутренне для выполнения кодирования. Рассмотрим этот класс в следующем разделе.

2.3. ЧарсетЭнкодер

ЧарсетЭнкодер преобразует символы Unicode в последовательность байтов для данного набора символов . Кроме того, он обеспечивает мелкозернистый контроль над процессом кодирования .

Давайте использовать этот класс для преобразования Струнные в byte массив:

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

Здесь мы создаем экземпляр ЧарсетЭнкодер позвонив в newEncoder метод на Чарсет объект.

Затем мы уточняем действия для условий ошибки, вызывая onMalformedInput() и onUnmappableCharacter () методы . Мы можем указать следующие действия:

Кроме того, мы используем заменитьС () метод определения замены byte массив.

Таким образом, мы заверим обзор различных подходов к преобразованию строки в массив byte. Давайте далее рассмотрим обратную операцию.

3. Преобразование byte Array в строку

Мы имеем в виду процесс преобразования byte массив к Струнные как декодирование . Как и кодирование, этот процесс требует Чарсет .

Тем не менее, мы не можем просто использовать любой charset для расшифровки массива byte. Мы должны использовать charset, который был использован для кодирования Струнные в byte массив .

Мы можем преобразовать массив byte в строку по-разному. Рассмотрим каждый из них в деталях.

3.1. Использование струнного конструктора

Струнные класс имеет несколько конструкторов, которые принимают byte массив в качестве входного . Все они похожи на getBytes метод, но работать в обратном направлении.

Во-первых, давайте преобразуем массив карт- Струнные использование 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);
}

Обратите внимание, что мы ничего не утверждаем здесь о содержании расшифрованной строки. Это происходит потому, что он может расшифровать что-то другое, в зависимости от набора символов платформы по умолчанию.

По этой причине, мы должны, как правило, избегать этого метода.

Во-вторых, давайте использовать именованный charset для декодирования:

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

Этот метод делает исключение, если названный charset недоступен на JVM.

В-третьих, Давайте использовать Чарсет объект для декодирования:

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

Наконец, давайте использовать стандартный Чарсет для того же:

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

До сих пор мы преобразовали byte массив в Струнные с помощью конструктора. Давайте теперь рассмотрим другие подходы.

3.2. Использование Charset.decode()

Чарсет класс обеспечивает декодировать () метод преобразования ByteBuffer Струнные :

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

Вот, недействительный вход заменяется символом замены по умолчанию для charset.

3.3. Чарсетдекодер

Все предыдущие подходы к расшифровке внутренне используют Чарсетдекодер класса. Мы можем использовать этот класс непосредственно для мелкозернистого контроля процесса декодирования :

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

Здесь мы заменяем недействительные входы и неподдерживаемые символы на “?”.

Если мы хотим быть информированными в случае недействительных входов, мы можем изменить декодер как:

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

4. Заключение

В этой статье мы исследовали несколько способов преобразования Струнные к массиву byte и обратному. Мы должны выбрать подходящий метод на основе входных данных, а также уровня контроля, необходимого для недействительных входных данных.

Как обычно, полный исходный код можно найти более на GitHub .