Строка в массив байтов, массив байтов в строку в Java
Сегодня мы узнаем, как преобразовать строку в массив байтов в java. Мы также узнаем, как преобразовать массив байтов в строку в Java.
Строка в байтовый массив
Мы можем использовать метод класса String getBytes() для кодирования строки в последовательность байтов, используя кодировку платформы по умолчанию. Этот метод перегружен, и мы также можем передать Charset в качестве аргумента. Вот простая программа, показывающая, как преобразовать строку в массив байтов в java.
package com.journaldev.util; import java.util.Arrays; public class StringToByteArray < public static void main(String[] args) < String str = "PANKAJ"; byte[] byteArr = str.getBytes(); // print the byte[] elements System.out.println("String to byte array: " + Arrays.toString(byteArr)); >>

byte[] byteArr = str.getBytes("UTF-8");
Однако, если мы укажем имя набора символов, нам придется либо перехватывать исключение UnsupportedEncodingException , либо выбрасывать его. Лучшим подходом является использование класса StandardCharsets , представленного в Java 1.7, как показано ниже.
byte[] byteArr = str.getBytes(StandardCharsets.UTF_8);
Вот и все способы преобразования строки в байтовый массив в java.
Массив байтов Java в строку
Давайте рассмотрим простую программу, показывающую, как преобразовать массив байтов в строку на Java.
package com.journaldev.util; public class ByteArrayToString < public static void main(String[] args) < byte[] byteArray = < 'P', 'A', 'N', 'K', 'A', 'J' >; byte[] byteArray1 = < 80, 65, 78, 75, 65, 74 >; String str = new String(byteArray); String str1 = new String(byteArray1); System.out.println(str); System.out.println(str1); > >

String str = new String(byteArray, StandardCharsets.UTF_8);
Класс String также имеет метод для преобразования подмножества массива байтов в строку.
byte[] byteArray1 = < 80, 65, 78, 75, 65, 74 >; String str = new String(byteArray1, 0, 3, StandardCharsets.UTF_8);
Вышеприведенный код совершенно прекрасен, и значение «str» будет «PAN». Это все о преобразовании массива байтов в строку в Java.
Вы можете проверить больше примеров массивов из нашего репозитория GitHub.
Ссылка: документ API getBytes
Преобразование строки в массив байтов и обратное в Java
Нам часто нужно преобразовать между строкой и массивом байтов в Java. В этом уроке мы подробно рассмотрим эти операции.
Во-первых, мы рассмотрим различные способы преобразования строки в массив байтов . Затем мы рассмотрим аналогичные операции в обратном порядке.
2. Преобразование строки в массив байтов
Строка хранится как массив символов Unicode в Java. Чтобы преобразовать его в массив байтов , мы переводим последовательность символов в последовательность байтов. Для этого перевода мы используем экземпляр Charset . Этот класс задает отображение между последовательностью символов s и последовательностью байтов s .
Мы называем описанный выше процесс кодированием .
В Java мы можем кодировать строку в массив байтов несколькими способами. Рассмотрим каждый из них подробно на примерах.
2.1. Использование String.getBytes()
Класс String предоставляет три перегруженных метода getBytes для кодирования строки в массив байтов :
- getBytes () — кодирует с использованием кодировки платформы по умолчанию.
- getBytes (String charsetName) — кодирует с использованием именованного набора символов
- getBytes (кодировка набора символов) — кодирует с использованием предоставленного набора символов
Во- первых, давайте закодируем строку, используя кодировку платформы по умолчанию:
String inputString = "Hello World!"; byte[] byteArrray = inputString.getBytes();
Вышеупомянутый метод зависит от платформы, так как он использует кодировку платформы по умолчанию. Мы можем получить этот набор символов, вызвав Charset.defaultCharset() .
Затем давайте закодируем строку, используя именованный набор символов:
@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); >
Этот метод создает исключение UnsupportedEncodingException , если именованная кодировка не поддерживается.
Поведение двух вышеуказанных версий не определено, если ввод содержит символы, не поддерживаемые кодировкой. Напротив, третья версия использует массив байтов замены набора символов по умолчанию для кодирования неподдерживаемого ввода.
Далее, давайте вызовем третью версию метода getBytes() и передадим экземпляр 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); >
Здесь мы используем фабричный метод Charset.forName для получения экземпляра Charset . Этот метод генерирует исключение времени выполнения, если имя запрошенного набора символов недопустимо. Он также генерирует исключение времени выполнения, если кодировка поддерживается в текущей JVM.
Тем не менее, некоторые наборы символов гарантированно доступны на каждой платформе Java. Класс StandardCharsets определяет константы для этих наборов символов.
Наконец, давайте закодируем, используя один из стандартных наборов символов:
@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 . Далее давайте рассмотрим метод, предоставляемый самим Charset .
2.2. Использование Charset.encode()
Класс Charset предоставляет удобный метод encode() , который кодирует символы Юникода в байты. Этот метод всегда заменяет недопустимый ввод и несопоставляемые символы, используя массив байтов замены по умолчанию для набора символов.
Давайте используем метод encode для преобразования строки в массив байтов :
@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); >
Как мы видим выше, неподдерживаемые символы были заменены байтом замены по умолчанию 63 набора символов.
Подходы, которые мы использовали до сих пор, используют класс CharsetEncoder внутри для выполнения кодирования. Давайте рассмотрим этот класс в следующем разделе.
2.3. кодировщик символов
CharsetEncoder преобразует символы Юникода в последовательность байтов для данного набора символов . Более того, он обеспечивает детальный контроль над процессом кодирования .
Давайте используем этот класс для преобразования строки в массив байтов :
@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); >
Здесь мы создаем экземпляр CharsetEncoder , вызывая метод newEncoder для объекта Charset .
Затем мы указываем действия для условий ошибки, вызывая методы onMalformedInput() и onUnmappableCharacter() . Мы можем указать следующие действия:
- IGNORE – отбросить ошибочный ввод
- REPLACE – заменить ошибочный ввод
- ОТЧЕТ — сообщить об ошибке, вернув объект CoderResult или создав исключение CharacterCodingException .
Кроме того, мы используем метод replaceWith() для указания замещающего массива байтов .
Таким образом, мы завершили рассмотрение различных подходов к преобразованию строки в массив байтов. Далее рассмотрим обратную операцию.
3. Преобразование массива байтов в строку
Мы называем процесс преобразования массива байтов в строку декодированием . Подобно кодированию, для этого процесса требуется Charset .
Однако мы не можем просто использовать любую кодировку для декодирования массива байтов. В частности, мы должны использовать набор символов, который закодировал строку в массив байтов .
Мы также можем преобразовать массив байтов в строку разными способами. Рассмотрим подробно каждый из них.
3.1. Использование конструктора строк
Класс String имеет несколько конструкторов, принимающих на вход массив байтов . Все они похожи на метод getBytes , но работают наоборот.
Итак , давайте преобразуем массив байтов в строку , используя кодировку платформы по умолчанию:
@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); >
Обратите внимание, что здесь мы ничего не утверждаем о содержимом декодированной строки. Это связано с тем, что он может декодировать что-то другое, в зависимости от кодировки платформы по умолчанию.
По этой причине мы обычно должны избегать этого метода.
Затем воспользуемся именованной кодировкой для декодирования:
@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); >
Этот метод создает исключение, если именованный набор символов недоступен в JVM.
Далее, давайте используем объект Charset для декодирования:
@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); >
До сих пор мы преобразовывали массив байтов в строку с помощью конструктора, а теперь рассмотрим другие подходы.
3.2. Использование Charset.decode()
Класс Charset предоставляет метод decode () , который преобразует ByteBuffer в 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); >
Здесь недопустимый ввод заменяется символом замены по умолчанию для набора символов.
3.3. CharsetDecoder
Обратите внимание, что все предыдущие подходы для внутреннего декодирования используют класс CharsetDecoder . Мы можем использовать этот класс напрямую для детального управления процессом декодирования :
@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. Вывод
В этой статье мы исследовали несколько способов преобразования строки в массив байтов и наоборот. Мы должны выбрать соответствующий метод на основе входных данных, а также уровень контроля, необходимый для недопустимых входных данных.
Как обычно, полный исходный код можно найти на GitHub .
- 1. Введение
- 2. Преобразование строки в массив байтов
- 2.1. Использование String.getBytes()
- 2.2. Использование Charset.encode()
- 2.3. кодировщик символов
- 3.1. Использование конструктора строк
- 3.2. Использование Charset.decode()
- 3.3. CharsetDecoder
2 примера для преобразования массива Byte [] в строку в Java
Преобразование байтового массива в String кажется простым, но трудно сделать это правильно. Многие программисты делают ошибку, игнорируя кодировку символов всякий раз, когда байты преобразуются в String или char или наоборот. Как программист, мы все знаем, что компьютер понимает только двоичные данные, то есть 0 и 1. Все, что мы видим и используем, например изображения, текстовые файлы, фильмы или любые другие мультимедийные файлы, хранится в виде байтов, но что более важно это процесс кодирования или декодирования байтов в символ. Преобразование данных является важной темой на любом собеседовании по программированию, и из-за хитрости кодирования символов эти вопросы являются одним из самых популярных вопросов о интервью в формате String в интервью Java. При чтении строки из входного источника, например, файлов XML, HTTP-запроса, сетевого порта или базы данных, вы должны обратить внимание на то, какую кодировку символов (например, UTF-8, UTF-16 и ISO 8859-1) они кодируют. Если вы не будете использовать ту же кодировку символов при преобразовании байтов в строку , вы получите поврежденную строку, которая может содержать совершенно неправильные значения. Вы могли видеть ?, квадратные скобки после преобразования byte [] в String, это из-за значений, которые ваша текущая кодировка символов не поддерживает, и просто показывает некоторые значения мусора.
Я пытался понять, почему программы делают ошибки кодирования символов чаще, чем нет, и мои небольшие исследования и собственный опыт позволяют предположить, что это может быть вызвано двумя причинами: во-первых, недостаточно для интернационализации и кодировки символов, а во-вторых, потому что символы ASCII поддерживаются почти все популярные схемы кодирования и имеют одинаковые значения. Поскольку мы в основном имеем дело с кодировкой, такой как UTF-8, Cp1252 и Windows-1252, которая отображает символы ASCII (в основном алфавиты и цифры) без сбоев, даже если вы используете другую схему кодирования. Настоящая проблема возникает, когда ваш текст содержит специальные символы, например «é» , который часто используется во французских именах. Если кодировка символов вашей платформы не распознает этот символ, то либо вы увидите другой символ, либо что-то в этом роде, и, к сожалению, пока вы не обожгете руки, вы вряд ли будете осторожны с кодировкой символов. В Java все немного сложнее, потому что многие классы ввода-вывода, например InputStreamReader, по умолчанию используют кодировку символов платформы. Это означает, что если вы запустите свою программу на другом компьютере, вы, скорее всего, получите другой вывод из-за разного кодирования символов, используемого на этом компьютере. В этой статье мы узнаем, как преобразовать byte [] в String в Java как с помощью JDK API, так и с помощью общих утилит Guava и Apache.
Как преобразовать byte [] в строку в Java
Есть несколько способов изменить байтовый массив на String в Java, вы можете использовать методы из JDK или использовать бесплатные API с открытым исходным кодом, такие как Apache commons и Google Guava. Этот API предоставляет как минимум два набора методов для создания байтового массива формы String; один, который использует кодировку платформы по умолчанию, а другой – кодировку символов. Вы всегда должны использовать позже, не полагайтесь на кодировку платформы. Я знаю, что это может быть то же самое, или вы, возможно, не сталкивались с какими-либо проблемами, но лучше быть в безопасности, чем потом сожалеть. Как я указывал в своем последнем посте о печати байтового массива в виде шестнадцатеричной строки , это также один из лучших способов указания кодировки символов при преобразовании байтов в символы на любом языке программирования. Возможно, ваш байтовый массив содержит непечатаемые символы ASCII. Давайте сначала посмотрим, как JDK преобразует byte [] в String:
-
Вы можете использовать конструктор String, который принимает байтовый массив и кодировку символов:
Преобразование из String в массив байтов и обратно
Вопрос: так как кириллица в юникоде имеет кодепойнты, превышающие 1 тысячу (кодепойнт буквы А , к примеру, равен 1040), а байт в Java может принимать значения от -128 до 127, следовательно при попытке преобразовать строку в массив типа byte должна происходить потеря информации, как следствие — при вызове метода toString() строка должна восстановиться некорректно. Но этого не произошло. В чем тут причина?
Отслеживать
задан 28 ноя 2018 в 14:20
485 5 5 серебряных знаков 20 20 бронзовых знаков1 ответ 1
Сортировка: Сброс на вариант по умолчанию
Это не юникод. String.getBytes() использует кодировку по-умолчанию платформы:
Encodes this String into a sequence of bytes using the platform’s default charset, storing the result into a new byte array.
Кодировка по-умолчанию задается настройками Java, ее можно проверить с помощью:
System.getProperty("file.encoding");Для получения байтов в юникоде, задайте кодировку явно:
byte[] bytes="новая строка".getBytes("UTF-8");Получится больше 12 байтов.
Обновление по вопросам в комментарии:
Разве UTF-8 выдает байты, эквивалентные юникодовскому представлению?
У юникода бывают разные представления. UTF-8 — одно из них.
Я знаю, что char выдает кодепойнты юникода. Если вывести System.out.println((byte)’н’), то это будет равно 61.
Здесь можно посмотреть как строчная кириллическая «н» представляется в разных кодировках: https://unicode-table.com/en/043D/
UTF-8:
Десятичное значение: 53437
Байты: 208 189UTF-16BE:
Десятичное значение: 1085
Байты: 4 61Для char в Java, согласно спецификации (§3.1 Unicode) используется кодировка UTF-16. Это тоже двухбайтовая кодировка. Соответственно, когда Вы приводите char к byte Вы получаете младший байт в этой кодировке.
Получить байты в «UTF-16BE» можно так:
byte[] bytes="новая строка".getBytes("UTF-16BE");Если вывести байты, как Вы предложили byte[] bytes=»новая строка».getBytes(«UTF-8»), то там первый байт равен -48, а не 61.
Кодировка UTF-8, как указано ранее беззнаковые (от 0 до 255) байты: 208 и 189. Знаковые байты, соответственно, -48 и -67.