Автор оригинала: 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 методы кодирования Струнные в карт- массив :
- getBytes () – кодирует с помощью charset платформы по умолчанию
- getBytes (String charsetName) – кодирует с помощью имени charset
- getBytes (Charset charset) – коды с использованием предоставленного charset
Во-первых, давайте закодируем строку с помощью 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 () методы . Мы можем указать следующие действия:
- IGNORE – падение ошибочного ввода
- REPLACE – заменить ошибочный вход
- РЕПОРТ – сообщите об ошибке, вернув КодерРесульт объект или бросание Кодирование символовИсключаемость
Кроме того, мы используем заменитьС () метод определения замены 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 .