Кодировать строку в UTF-8 в Java

Введение При работе со строками в Java нам часто требуется кодировать их в определенной кодировке, такой как UTF-8. > UTF-8 представляет собой кодировку символов переменной ширины, которая использует от одного до четырех восьмибитных байтов для представления всех допустимых кодовых точек Unicode. Кодовая точка может представлять отдельные символы, но также может иметь другие значения, например, для форматирования. "Переменная ширина" означает, что он кодирует каждую кодовую точку с разным количеством байтов (от одного до четырех) и как пробел-sa

Вступление

При работе со строками в Java нам часто требуется кодировать их в определенной кодировке, такой как UTF-8 .

UTF-8 представляет собой кодировку символов переменной ширины, которая использует от одного до четырех восьмибитных байтов для представления всех допустимых кодовых точек Unicode .

Кодовая точка может представлять отдельные символы, но также может иметь другие значения, например, для форматирования. «Переменная ширина» означает, что он кодирует каждую кодовую точку с различным количеством байтов (от одного до четырех), и в качестве меры экономии места обычно используемые кодовые точки представлены меньшим количеством байтов, чем те, которые используются реже.

UTF-8 использует один байт для представления кодовых точек от 0 до 127 , что делает первые 128 кодовых точек однозначным отображением с символами ASCII, поэтому UTF-8 обратно совместим с ASCII.

Примечание. Java кодирует все строки в UTF-16, в котором для хранения кодовых точек используется минимум два байта. Зачем тогда нужно преобразовывать в UTF-8?

Не весь ввод может быть в кодировке UTF-16 или UTF-8, если на то пошло. На самом деле вы можете получить строку в кодировке ASCII, которая не поддерживает такое количество символов, как UTF-8. Кроме того, не весь вывод может обрабатывать UTF-16, поэтому имеет смысл преобразовать его в более универсальный UTF-8.

Мы будем работать с несколькими строками, которые содержат символы Unicode, с которыми вы, возможно, не сталкиваетесь ежедневно, - например, č , ß и, имитирующие ввод данных пользователем.

Выпишем пару строк:

 String serbianString = "Šta radiš?"; // What are you doing? 
 String germanString = "Wie heißen Sie?"; // What's your name? 
 String japaneseString = "よろしくお願いします"; // Pleased to meet you. 

Теперь давайте воспользуемся конструктором String(byte[] bytes, Charset charset) для String, чтобы воссоздать эти строки, но с другим Charset символов, имитирующим ввод ASCII, который пришел к нам в первую очередь:

 String asciiSerbianString = new String(serbianString.getBytes(), StandardCharsets.US_ASCII); 
 String asciigermanString = new String(germanString.getBytes(), StandardCharsets.US_ASCII); 
 String asciijapaneseString = new String(japaneseString.getBytes(), StandardCharsets.US_ASCII); 
 
 System.out.println(asciiSerbianString); 
 System.out.println(asciigermanString); 
 System.out.println(asciijapaneseString); 

После того, как мы создали эти строки и закодировали их как символы ASCII, мы можем распечатать их:

 ��ta radi��? 
 Wie hei��en Sie? 
 ������������������������������ 

В то время как первые две строки содержат всего несколько символов, которые не являются допустимыми символами ASCII, последняя не содержит их .

Чтобы избежать этой проблемы, мы можем предположить, что не весь ввод уже может быть закодирован по нашему вкусу, и закодировать его, чтобы самостоятельно устранить такие случаи. Есть несколько способов кодирования строки в UTF-8 в Java:

Кодирование строки в Java просто означает вставку определенных байтов в массив байтов, составляющий строку, - предоставление дополнительной информации, которая может быть использована для ее форматирования после того, как мы сформируем экземпляр String

Использование метода getBytes ()

Класс String , состоящий из байтов, естественно, предлагает getBytes() , который возвращает массив байтов, используемый для создания String. Поскольку кодирование на самом деле просто манипулирует этим массивом байтов, мы можем пропустить этот массив через Charset чтобы сформировать его при получении данных.

По умолчанию, без предоставления Charset , байты кодируются с использованием Charset платформ по умолчанию, который может быть не UTF-8 или UTF-16. Давайте возьмем байты String и распечатаем их:

 String serbianString = "Šta radiš?"; // What are you doing? 
 byte[] bytes = serbianString.getBytes(StandardCharsets.UTF_8); 
 
 for (byte b : bytes) { 
 System.out.print(String.format("%s ", b)); 
 } 

Это выводит:

 -59 -96 116 97 32 114 97 100 105 -59 -95 63 

Это кодовые точки для наших закодированных символов, и они не очень полезны для человеческого глаза. Хотя, опять же, мы можем использовать конструктор String для создания удобочитаемой строки из этой самой последовательности. Учитывая тот факт, что мы закодировали этот массив байтов в UTF_8 , мы можем продолжить и безопасно создать новую строку из этого:

 String utf8String = new String(bytes); 
 System.out.println(utf8String); 

Примечание. Вместо того, чтобы кодировать их с помощью getBytes() , вы также можете кодировать байты с помощью конструктора String:

 String utf8String = new String(bytes, StandardCharsets.UTF_8); 

Теперь это выводит ту же строку, с которой мы начали, но в кодировке UTF-8:

 Šta radiš? 

Закодируйте строку в UTF-8 с помощью Java 7 StandardCharsets

Начиная с Java 7 , мы познакомились с StandardCharsets , который имеет несколько Charset таких как US_ASCII , ISO_8859_1 , UTF_8 и UTF-16 среди других.

Каждый Charset имеет encode() и decode() , которые принимают CharBuffer (который implements CharSequence , как String ). На практике это означает, что мы можем вставить String в методы encode() Charset .

Метод encode() возвращает ByteBuffer который мы можем легко снова превратить в String.

Раньше, когда мы использовали наш getBytes() , мы сохраняли полученные байты в массиве байтов, но при использовании StandardCharsets все немного по-другому. Сначала нам нужно использовать класс ByteBuffer для хранения наших байтов. Затем нам нужно как кодировать, так и декодировать обратно наши недавно выделенные байты. Посмотрим, как это работает в коде:

 String japaneseString = "よろしくお願いします"; // Pleased to meet you. 
 
 ByteBuffer byteBuffer = StandardCharsets.UTF_8.encode(japaneseString); 
 
 String utf8String = new String(byteBuffer.array(), StandardCharsets.UTF_8); 
 System.out.println(utf8String); 

Выполнение этого кода приводит к:

よろしくお願いします 

Закодируйте строку в UTF-8 с помощью Apache Commons

Пакет кодеков Apache Commons содержит простые кодировщики и декодеры для различных форматов, таких как Base64 и Hexadecimal . Помимо этих широко используемых кодеров и декодеров, пакет кодеков также поддерживает набор утилит фонетического кодирования .

Чтобы мы могли использовать кодек Apache Commons, нам нужно добавить его в наш проект в качестве внешней зависимости.

Используя Maven, давайте добавим commons-codec к нашему файлу pom.xml

 <dependency> 
 <groupId>commons-codec</groupId> 
 <artifactId>commons-codec</artifactId> 
 <version>1.15</version> 
 </dependency> 

В качестве альтернативы, если вы используете Gradle:

 compile 'commons-codec:commons-codec:1.15' 

Теперь мы можем использовать служебные классы Apache Commons - и, как обычно, мы будем использовать класс StringUtils

Это позволяет нам преобразовывать строки в байты и обратно, используя различные кодировки, требуемые спецификацией Java. Этот класс является нулевым и потокобезопасным, поэтому у нас есть дополнительный уровень защиты при работе со строками.

Чтобы закодировать String в UTF-8 с StringUtils класса StringUtils Apache Common, мы можем использовать метод getBytesUtf8() , который работает так же, как метод getBytes() с указанным Charset :

 String germanString = "Wie heißen Sie?"; // What's your name? 
 byte[] bytes = StringUtils.getBytesUtf8(germanString); 
 String utf8String = StringUtils.newStringUtf8(bytes); 
 System.out.println(utf8String); 

Это приводит к:

 Wie heißen Sie? 

Или вы можете использовать обычный класс StringUtils из зависимости commons-lang3

 <dependency> 
 <groupId>org.apache.commons</groupId> 
 <artifactId>commons-lang3</artifactId> 
 </dependency> 

Если вы используете Gradle:

 implementation group: 'org.apache.commons', name: 'commons-lang3', version: ${version} 

И теперь мы можем использовать тот же подход, что и с обычными строками:

 String germanString = "Wie heißen Sie?"; // What's your name? 
 byte[] bytes = StringUtils.getBytes(germanString, StandardCharsets.UTF_8); 
 String utf8String = StringUtils.toEncodedString(bytes, StandardCharsets.UTF_8); 
 System.out.println(utf8String); 

Хотя этот подход является потокобезопасным и нулевым:

 Wie heißen Sie? 

Заключение

В этом руководстве мы рассмотрели, как кодировать строку Java в UTF-8 . Мы рассмотрели несколько подходов - создание String вручную с помощью getBytes() и управление ими, StandardCharsets а также Apache Commons.

comments powered by Disqus