Сколько байтов занимает один символ Unicode? - PullRequest
212 голосов
/ 13 марта 2011

Я немного запутался в кодировках.Насколько я знаю, старые символы ASCII занимали один байт на символ.Сколько байтов требуется для символа Юникода?

Я предполагаю, что один символ Unicode может содержать все возможные символы из любого языка - я прав?Так сколько байт нужно для каждого символа?

А что означают UTF-7, UTF-6, UTF-16 и т. Д.?Это разные версии Unicode?

Я прочитал статью Википедии о Unicode , но это довольно сложно для меня.Я с нетерпением жду простого ответа.

Ответы [ 10 ]

173 голосов
/ 26 октября 2015

Как ни странно, никто не указал, как рассчитать, сколько байтов занимает один символ Unicode.Вот правило для строк в кодировке UTF-8:

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation bytes (1-3 continuation bytes)
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF4   First byte of a 4-byte character encoding

Итак, быстрый ответ: он занимает от 1 до 4 байтов, в зависимости от первого, который будет указывать, сколько байтов он займет.

Обновление

Как указано prewett , это правило применяется только к UTF-8

130 голосов
/ 13 марта 2011

Вы не увидите простого ответа, потому что его нет.

Во-первых, Unicode не содержит «каждого символа из каждого языка», хотя, безусловно, пытается.

Юникод сам по себе является отображением, он определяет кодовые точки, а кодовая точка - это число, связанное с обычно символом. Обычно я говорю, потому что есть такие понятия, как объединение персонажей. Вы можете быть знакомы с такими вещами, как акценты или умлауты. Их можно использовать с другим символом, например a или u, для создания нового логического символа. Следовательно, символ может состоять из 1 или более кодовых точек.

Чтобы быть полезным в вычислительных системах, нам нужно выбрать представление для этой информации. Это различные Unicode-кодировки, такие как utf-8, utf-16le, utf-32 и т. Д. Они отличаются в основном размером их кодовых блоков. UTF-32 - простейшая кодировка, она имеет кодовый блок 32 бита, что означает, что отдельная кодовая точка удобно вписывается в кодовый блок. В других кодировках могут возникнуть ситуации, когда для кодовой точки потребуется несколько кодовых единиц или эта конкретная кодовая точка вообще не может быть представлена ​​в кодировке (это проблема, например, для UCS-2).

Из-за гибкости объединения символов даже в пределах заданной кодировки количество байтов на символ может варьироваться в зависимости от символа и формы нормализации. Это протокол для работы с символами, которые имеют более одного представления (вы можете сказать "an 'a' with an accent", что составляет 2 кодовые точки, одна из которых представляет собой объединяющий символ или "accented 'a'", который является одной кодовой точкой).

36 голосов
/ 01 мая 2014

Я знаю, что этот вопрос старый и уже имеет принятый ответ, но я хочу предложить несколько примеров (надеюсь, что он кому-нибудь пригодится).

Насколько я знаю, старые символы ASCII занимали один байт на символ.

правый. На самом деле, поскольку ASCII является 7-битной кодировкой, он поддерживает 128 кодов (95 из которых можно распечатать), поэтому он использует только половину байта (если это имеет смысл).

Сколько байтов требуется для символа Юникода?

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

Я предполагаю, что один символ Unicode может содержать все возможные персонаж с любого языка - я прав?

Нет. Но почти. Так что в основном да. Но все же нет.

Так сколько байт ему нужно на символ?

То же, что ваш второй вопрос.

А что означают UTF-7, UTF-6, UTF-16 и т. Д.? Это какой-то юникод версии?

Нет, это кодировки. Они определяют, как байты / октеты должны представлять символы Юникода.

Пара примеров. Если некоторые из них не могут быть отображены в вашем браузере (возможно, из-за того, что шрифт не поддерживает их), перейдите к http://codepoints.net/U+1F6AA (замените 1F6AA на шестнадцатеричный код), чтобы увидеть изображение.

    • U + 0061 ЛАТИНСКОЕ МАЛЕНЬКОЕ ПИСЬМО A: a
      • Nº: 97
      • UTF-8: 61
      • UTF-16: 00 61
    • U + 00A9 АВТОРСКИЙ ЗНАК: ©
      • Nº: 169
      • UTF-8: C2 A9
      • UTF-16: 00 A9
    • U + 00AE ЗАРЕГИСТРИРОВАННЫЙ ЗНАК: ®
      • Nº: 174
      • UTF-8: C2 AE
      • UTF-16: 00 AE
    • U + 1337 ЭТИОПИЧЕСКИЙ СЛОВНЫЙ PHWA:
      • Nº: 4919
      • UTF-8: E1 8C B7
      • UTF-16: 13 37
    • U + 2014 EM DASH:
      • Nº: 8212
      • UTF-8: E2 80 94
      • UTF-16: 20 14
    • U + 2030 В МИЛЛЕ ЗНАК:
      • Nº: 8240
      • UTF-8: E2 80 B0
      • UTF-16: 20 30
    • U + 20AC ЗНАК ЕВРО:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 AC
    • U + 2122 ЗНАК ТОРГОВОЙ МАРКИ:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22 * ​​1132 *
    • U + 2603 Снеговик:
      • Nº: 9731
      • UTF-8: E2 98 83
      • UTF-16: 26 03
    • U + 260E ЧЕРНЫЙ ТЕЛЕФОН:
      • Nº: 9742
      • UTF-8: E2 98 8E
      • UTF-16: 26 0E
    • U + 2614 ЗОНТИК с каплями дождя:
      • Nº: 9748
      • UTF-8: E2 98 94
      • UTF-16: 26 14
    • U + 263A БЕЛЫЙ УЛЫБАЮЩИЙСЯ ЛИЦО:
      • Nº: 9786
      • UTF-8: E2 98 BA
      • UTF-16: 26 3A
    • U + 2691 ЧЕРНЫЙ ФЛАГ:
      • Nº: 9873
      • UTF-8: E2 9A 91
      • UTF-16: 26 91
    • U + 269B СИМВОЛ АТОМА:
      • Nº: 9883
      • UTF-8: E2 9A 9B
      • UTF-16: 26 9B
    • U + 2708 САМОЛЕТ:
      • Nº: 9992
      • UTF-8: E2 9C 88
      • UTF-16: 27 08
    • U + 271E БЕЛЫЙ ЛАТИНСКИЙ КРЕСТ БЕЛЫЙ
      • Nº: 10014
      • UTF-8: E2 9C 9E
      • UTF-16: 27 1E
    • U + 3020 ПОЧТА МАРКА ЛИЦА:
      • Nº: 12320
      • UTF-8: E3 80 A0
      • UTF-16: 30 20
    • U + 8089 CJK UNIFIED IDEOGRAPH-8089:
      • Nº: 32905
      • UTF-8: E8 82 89
      • UTF-16: 80 89
    • U + 1F4A9 КУКЛА ПОО: ?
      • Nº: 128169
      • UTF-8: F0 9F92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 РАКЕТА: ?
      • Nº: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Хорошо, меня возятпрочь ...

Забавные факты:

  • Если вы ищете определенный символ, вы можете скопировать и вставить его на http://codepoints.net/.
  • Я потратил много временивремени в этом бесполезном списке (но он отсортирован!).
  • В MySQL есть кодировка "utf8", которая на самом деле не поддерживает символы длиннее 3 байтов.Так что вы не можете вставить кучу пу , поле будет молча обрезано.Вместо этого используйте "utf8mb4".
  • Есть тестовая страница снеговика (unicodesnowmanforyou.com) .
28 голосов
/ 13 марта 2011

Проще говоря, Unicode - это стандарт, который присваивает один номер (называемый кодовой точкой) всем символам мира (он все еще находится в стадии разработки).

Теперь вам нужно представить эту кодовую точку, используя байты, которые называются character encoding. UTF-8, UTF-16, UTF-6 - способы представления этих символов.

UTF-8 - многобайтовая кодировка символов. Символы могут иметь от 1 до 6 байтов (некоторые из них могут не потребоваться прямо сейчас).

UTF-32 каждый символ имеет 4 байта символа.

UTF-16 использует 16 битов для каждого символа и представляет только часть символов Юникода, называемых BMP (для всех практических целей этого достаточно). Java использует эту кодировку в своих строках.

13 голосов
/ 27 августа 2016

В UTF-8:

1 byte:       0 -     7F     (ASCII)
2 bytes:     80 -    7FF     (all European plus some Middle Eastern)
3 bytes:    800 -   FFFF     (multilingual plane incl. the top 1792 and private-use)
4 bytes:  10000 - 10FFFF

В UTF-16:

2 bytes:      0 -   D7FF     (multilingual plane except the top 1792 and private-use )
4 bytes:   D800 - 10FFFF

В UTF-32:

4 bytes:      0 - 10FFFF

10FFFF - последний Unicodeкодовая точка по определению, и она определена таким образом, потому что это технический предел UTF-16.

Это также самая большая кодовая точка, которую UTF-8 может кодировать в 4 байта, но идея кодирования UTF-8 также работает для 5и 6-байтовые кодировки для покрытия кодовых точек до 7FFFFFFF, т.е.половина того, что может UTF-32.

8 голосов
/ 13 марта 2011

В Unicode ответ дается нелегко. Проблема, как вы уже указали, заключается в кодировках.

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

Единственная кодировка, где (на данный момент) мы можем сделать утверждение о размере, это UTF-32. Там всегда 32 бит на символ, хотя я представляю, что кодовые точки подготовлены для будущего UTF-64:)

Что делает это настолько трудным, это как минимум две вещи:

  1. составленные символы, где вместо использования уже существующего акцентированного / диакритического знака (À), пользователь решил объединить ударение и базовый символ (`A).
  2. кодовые точки. Кодовые точки - это метод, с помощью которого кодировки UTF позволяют кодировать больше, чем обычно позволяет число битов, которое дает им их имя. Например. UTF-8 обозначает определенные байты, которые сами по себе являются недопустимыми, но когда за ними следует действительный байт продолжения, он позволяет описать символ за пределами 8-битного диапазона 0..255. См. Примеры и Overlong Encodings ниже в статье Википедии о UTF-8.
    • Отличный пример, приведенный здесь, состоит в том, что символ € (кодовая точка U+20AC может быть представлен либо как трехбайтовая последовательность E2 82 AC, либо четырехбайтовая последовательность F0 82 82 AC.
    • Оба действительны, и это показывает, насколько сложен ответ, когда речь идет о «Юникоде», а не о конкретной кодировке Юникода, такой как UTF-8 или UTF-16.
7 голосов
/ 03 августа 2013

В UTF-8 есть отличный инструмент для вычисления байтов любой строки: http://mothereff.in/byte-counter

Обновление: @mathias опубликовал код: https://github.com/mathiasbynens/mothereff.in/blob/master/byte-counter/eff.js

4 голосов
/ 13 марта 2011

Ну, я только что поднял страницу Wikipedia на ней, и во вступительной части я увидел, что «Юникод может быть реализован различными кодировками символов. Наиболее часто используемые кодировки - это UTF-8 (который использует один байт для любых символов ASCII). , которые имеют одинаковые значения кода в кодировке UTF-8 и ASCII и до четырех байтов для других символов), теперь устаревший UCS-2 (который использует два байта для каждого символа, но не может кодировать каждый символ в текущем Unicode стандарт) "

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

Итак, ваш простой ответ, который вам нужен, это то, что он меняется.

3 голосов
/ 12 июля 2016

Для UTF-16 персонажу нужны четыре байта (две кодовые единицы), если он начинается с 0xD800 или больше; такой персонаж называется «суррогатная пара». В частности, суррогатная пара имеет вид:

[0xD800 - 0xDBFF]  [0xDC00 - 0xDFF]

где [...] указывает двухбайтовую кодовую единицу с заданным диапазоном. Все, что <= 0xD7FF - это одна кодовая единица (два байта). Все>> 0xE000 недопустимо (за исключением маркеров спецификации, возможно).

См. http://unicodebook.readthedocs.io/unicode_encodings.html, раздел 7.5.

1 голос
/ 09 октября 2013

Проверьте это Конвертер кодов Unicode .Например, введите 0x2009, где 2009 - номер Unicode для тонкого пробела , в поле «0x ... нотация» и нажмите «Преобразовать».Шестнадцатеричное число E2 80 89 (3 байта) появляется в поле «Единицы кода UTF-8».

...