Разница между UTF-8 и UTF-16?
Разница между UTF-8 и UTF-16? Зачем нам это нужно?
MessageDigest md = MessageDigest.getInstance("SHA-256");
String text = "This is some text";
md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed
byte[] digest = md.digest();
4 ответа
Я полагаю, что есть много хороших статей об этом в Интернете, но вот краткое резюме.
И UTF-8, и UTF-16 являются кодировками переменной длины. Однако в UTF-8 символ может занимать минимум 8 битов, тогда как в UTF-16 длина символа начинается с 16 битов.
Основные плюсы UTF-8:
- Основные символы ASCII, такие как цифры, латинские символы без акцентов и т. Д., Занимают один байт, который идентичен представлению US-ASCII. Таким образом, все строки US-ASCII становятся действительными UTF-8, что обеспечивает приличную обратную совместимость во многих случаях.
- Отсутствие нулевых байтов, что позволяет использовать строки с нулевым символом в конце, что также обеспечивает большую обратную совместимость.
- UTF-8 не зависит от порядка байтов, поэтому вам не нужно беспокоиться о проблеме Big Endian / Little Endian.
Основные минусы UTF-8:
- Многие обычные символы имеют разную длину, что замедляет индексацию по кодам и ужасно вычисляет количество кодов.
- Даже если порядок байтов не имеет значения, иногда в UTF-8 все еще имеется спецификация (метка порядка байтов), которая служит для уведомления о том, что текст кодируется в UTF-8, а также нарушает совместимость с программным обеспечением ASCII, даже если текст содержит только символы ASCII., Программное обеспечение Microsoft (например, Блокнот) особенно любит добавлять спецификации в UTF-8.
Основные плюсы UTF-16:
- Символы BMP (базовая многоязычная плоскость), включая латиницу, кириллицу, большинство китайских языков (КНР сделала поддержку некоторых кодовых точек вне BMP обязательной), большинство японских языков могут быть представлены 2 байтами. Это ускоряет индексирование и вычисление количества кодовых точек в случае, если текст не содержит дополнительных символов.
- Даже если в тексте есть дополнительные символы, они по-прежнему представлены парами 16-битных значений, что означает, что общая длина по-прежнему делится на два и позволяет использовать 16-битные
char
в качестве примитивного компонента строки.
Основные минусы UTF-16:
- Много нулевых байтов в строках US-ASCII, что означает отсутствие строк с нулевым символом в конце и много потерянной памяти.
- Использование его в качестве кодировки фиксированной длины "в основном работает" во многих распространенных сценариях (особенно в США / ЕС / странах с кириллицей / Израилем / арабскими странами / Ираном и многими другими), что часто приводит к нарушению поддержки, где это не так. Это означает, что программисты должны знать о суррогатных парах и правильно обращаться с ними в тех случаях, когда это важно!
- Это переменная длина, поэтому подсчет или индексирование кодовых точек обходятся дорого, хотя и меньше, чем UTF-8.
В общем, UTF-16 обычно лучше для представления в памяти, потому что BE/LE там не имеет значения (просто используйте собственный порядок), а индексирование выполняется быстрее (просто не забудьте правильно обрабатывать суррогатные пары). UTF-8, с другой стороны, чрезвычайно хорош для текстовых файлов и сетевых протоколов, потому что здесь нет проблемы BE/LE и часто бывает полезно нулевое завершение, а также ASCII-совместимость.
Это просто разные схемы для представления символов Unicode.
Оба имеют переменную длину - UTF-16 использует 2 байта для всех символов в базовой многоязычной плоскости (BMP), которая содержит большинство символов общего пользования.
UTF-8 использует от 1 до 3 байтов для символов в BMP, до 4 для символов в текущем диапазоне Unicode от U+0000 до U+1FFFFF и расширяется до U+7FFFFFFF, если это когда-либо становится необходимым... но особенно все символы ASCII представлены одним байтом каждый.
Для целей дайджеста сообщений не имеет значения, какой из них вы выберете, если каждый, кто пытается воссоздать дайджест, использует один и тот же параметр.
Смотрите эту страницу для получения дополнительной информации о UTF-8 и Unicode.
(Обратите внимание, что все символы Java являются кодовыми точками UTF-16 в BMP; для представления символов выше U+FFFF необходимо использовать суррогатные пары в Java.)
Безопасность: используйте только UTF-8
Разница между UTF-8 и UTF-16? Зачем нам это нужно?
В реализациях UTF-16 было по крайней мере несколько уязвимостей безопасности. Смотрите Википедию для деталей.
WHATWG и W3C объявили, что в Интернете должен использоваться только UTF-8.
Проблемы [безопасности], изложенные здесь, исчезают при использовании исключительно UTF-8, что является одной из многих причин, по которым теперь применяется обязательное кодирование для всех вещей.
Другие группы говорят то же самое.
Таким образом, хотя UTF-16 может продолжать использоваться внутри некоторых систем, таких как Java и Windows, то малое использование UTF-16, которое вы видели в прошлом для файлов данных, обмена данными и т. Д., Вероятно, полностью исчезнет.
Это не связано с UTF-8/16 (в общем, хотя оно и преобразуется в UTF16, и часть BE/LE может быть установлена с одной строкой), но ниже приведен самый быстрый способ преобразования строки в байт []. Например: хорошо подходит для указанного случая (хэш-код). String.getBytes(enc) относительно медленный.
static byte[] toBytes(String s){
byte[] b=new byte[s.length()*2];
ByteBuffer.wrap(b).asCharBuffer().put(s);
return b;
}
Простой способ различить UTF-8 и UTF-16 состоит в том, чтобы определить общие черты между ними.
За исключением совместного использования одного и того же номера Юникода для данного символа, каждый из них имеет свой собственный формат.