Разница между 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 126

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;
    }

простой способ дифференцировать UTF-8 и UTF-16 заключается в выявлении общих черт между ними.

кроме совместного использования одного и того же номера Юникода для данного символа, каждый из них является их собственным форматом.