Разница между 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, такие как цифры, латинские символы без акцентов и т. д. занимают один байт, который идентичен нам-ASCII представление. Этот таким образом, все строки US-ASCII становятся действительными UTF-8, что обеспечивает достойную обратную совместимость во многих случаях.
- нет нулевых байтов, что позволяет использовать строки с нулевым завершением, это также вводит большую обратную совместимость.
- UTF-8 не зависит от порядка байтов, поэтому вам не нужно беспокоиться о большой проблеме Endian / Little Endian.
основные минусы UTF-8:
- многие общие символы имеют разную длину, что замедляет индексацию по кодовой точке и вычислению количества кодовых точек ужасно.
- несмотря на то, что порядок байтов не имеет значения, иногда UTF-8 все еще имеет BOM (Знак порядка байтов), который служит для уведомления о том, что текст закодирован в 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 и null-termination часто пригодится, а также 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/16 (в общем случае, хотя он преобразуется в UTF16 и часть BE/LE может быть установлена с одной строкой), но ниже приведен самый быстрый способ преобразования строки в байт[]. Например: хорошо именно для данного случая (хэш-код). Строка.getBytes (enc) является относительно медленным.
static byte[] toBytes(String s){ byte[] b=new byte[s.length()*2]; ByteBuffer.wrap(b).asCharBuffer().put(s); return b; }