Сколько символов может кодировать UTF-8?


97

Если UTF-8 имеет 8 бит, не означает ли это, что может быть не более 256 различных символов?

Первые 128 кодовых точек такие же, как в ASCII. Но в нем говорится, что UTF-8 может поддерживать до миллиона символов?

Как это работает?


2
Не могли бы вы переоценить этот вопрос, потому что все ответы неверны. Прочтите мой ответ: stackoverflow.com/a/45042566/124486
Эван Кэрролл,

В кодировках Юникода UTF-8, UTF-16, UTF-32 число - это количество битов в его кодовых единицах , одна или несколько из которых кодируют кодовую точку Юникода.
Том Блоджет

1
Я ответил на этот вопрос некоторое время назад в попытке исправить его: было бы здорово, если бы вы взвесили его против выбранного ответа, который буквально представляет собой всего лишь одну цитату из Википедии, которая не рассказывает всей истории (надеюсь, мое обновление намного яснее)
Эван Кэрролл

Ответы:


135

UTF-8 не использует все время один байт, это от 1 до 4 байтов.

Для первых 128 символов (US-ASCII) требуется один байт.

Следующим 1920 символам требуется два байта для кодирования. Это покрывает оставшуюся часть почти всех латинских алфавитов, а также греческий, кириллический, коптский, армянский, еврейский, арабский, сирийский и танский алфавиты, а также комбинированные диакритические знаки.

Три байта необходимы для символов в остальной части базовой многоязычной плоскости, которая содержит практически все широко используемые символы [12], включая большинство китайских, японских и корейских [CJK] символов.

Четыре байта необходимы для символов в других плоскостях Unicode, которые включают менее распространенные символы CJK, различные исторические сценарии, математические символы и эмодзи (пиктографические символы).

источник: Википедия


привет @zwippie, я новичок в этом. Есть кое-что, чего я не понимаю.! BMP использует 2 байта, вы говорите, это 3? я ошибся?
chiperortiz 03

1
@chiperortiz, BMP действительно 16-битный, поэтому его можно закодировать как UTF-16 с постоянной длиной на символ (UTF-16 также поддерживает выход за пределы 16 бит, но это сложная практика, и многие реализации не поддерживают его). Однако для UTF-8 вам также нужно закодировать, как долго он будет длиться, поэтому вы потеряете некоторые биты. Вот почему вам нужно 3 байта для полного кодирования BMP. Это может показаться расточительным, но помните, что UTF-16 всегда использует 2 байта, а UTF-8 использует один байт на символ для большинства символов латинского языка. Делает его вдвое компактнее.
sanderd17

Основная направленность вопроса OP связана с тем, почему он называется UTF- 8 - это на самом деле не дает ответа.
jbyrd

40

UTF-8 использует 1–4 байта на символ: один байт для символов ascii (первые 128 значений Unicode такие же, как и ascii). Но для этого требуется всего 7 бит. Если установлен самый высокий («знаковый») бит, это указывает начало многобайтовой последовательности; количество последовательных установленных высоких битов указывает количество байтов, затем 0, а оставшиеся биты вносят вклад в значение. Для других байтов два старших бита будут 1 и 0, а оставшиеся 6 бит - это значение.

Таким образом, четырехбайтовая последовательность начинается с 11110 ... (и ... = три бита для значения), затем трех байтов по 6 бит для каждого значения, что дает 21-битное значение. 2 ^ 21 превышает количество символов Юникода, поэтому весь Юникод может быть выражен в UTF8.


@NickL. Нет, я имею ввиду 3 байта. В этом примере, если первый байт последовательности многобайтном начинается 1111, первый 1 указывает на то, что это начало последовательности многобайтном, то число последовательных 1 после того, как, что указывает число дополнительных байтов в последовательности (так что первый байт начинается со 110, 1110 или 11110).
CodeClown42 02

Нашел подтверждение своим словам в RFC 3629. tools.ietf.org/html/rfc3629#section-3 . Однако я не понимаю, зачем мне ставить «10» в начале второго байта 110xxxxx 10xxxxxx? Почему не просто 110xxxxx xxxxxxxx?
колобок

3
Нашел ответ в softwareengineering.stackexchange.com/questions/262227/… . Только по соображениям безопасности (в случае , если один байт в середине потока поврежден)
Колобок

@kolobok А. Без безопасности вы можете затем закодировать 21-битное значение в 3 байта (3 бита, указывающие длину, плюс 21 бит). : D Наверное, это не так уж и важно, по крайней мере, WRT западные языки.
CodeClown42 06

Я предполагаю, что NickL спросил об этом, но что случилось с остальными битами в этом первом байте, если ... представляет последующие байты вместо битов?
c6754

27

Согласно этой таблице * UTF-8 должен поддерживать:

2 31 = 2 147 483 648 символов

Однако RFC 3629 ограничил возможные значения, поэтому теперь мы ограничены 4 байтами , что дает нам

2 21 = 2097152 символа

Обратите внимание, что значительная часть этих символов «зарезервирована» для пользовательского использования, что на самом деле очень удобно для иконок-шрифтов.

* Википедия показывала таблицу с 6 байтами - с тех пор они обновили статью.

2017-07-11: Исправлено двойное подсчет одной и той же кодовой точки, закодированной несколькими байтами


Этот ответ - двойной подсчет количества возможных кодировок. После того, как вы посчитали все 2 ^ 7, вы не сможете пересчитать их снова в 2 ^ 11, 2 ^ 16 и т. Д. Правильное количество возможных кодировок - 2 ^ 21 (хотя не все в настоящее время используются).
Джимми

@ Джимми Ты уверен, что я считаю дважды? 0xxxxxxxдает 7 используемых битов, 110xxxxx 10xxxxxxдает еще 11 - перекрытия нет. Первый байт начинается с 0в первом случае, а 1во втором случае.
mpen

@mpen так какой код 00000001хранит, а что 11000000 100000001хранит?
Эван Кэрролл,

1
@EvanCarroll Эээ .... точка взята. Не осознавал, что существует несколько способов кодирования одной и той же кодовой точки.
mpen

1
Я пошел дальше и попытался сам ответить на этот вопрос, посмотрите, считаете ли вы, что это лучшее объяснение и ответ на вопрос: stackoverflow.com/a/45042566/124486
Эван Кэрролл

21

Юникод против UTF-8

Юникод преобразует кодовые точки в символы. UTF-8 - это механизм хранения Unicode. Unicode имеет спецификацию. UTF-8 имеет спецификацию. У них обоих разные пределы. UTF-8 имеет другую границу вверх.

Unicode

Юникод обозначается словом «плоскости». Каждый самолет несет 2 16 кодовых точек. В Юникоде 17 самолетов. Всего 17 * 2^16кодовых точек. Первая плоскость, плоскость 0 или BMP , является особенной в весе , что он несет.

Вместо того, чтобы объяснять все нюансы, я просто процитирую вышеупомянутую статью о самолетах.

На 17 самолетах можно разместить 1114 112 кодовых точек. Из них 2048 являются суррогатами, 66 не являются символами и 137 468 зарезервированы для частного использования, а 974 530 - для публичного использования.

UTF-8

Теперь вернемся к статье, указанной выше,

Схема кодирования, используемая UTF-8, была разработана с гораздо большим пределом в 2 31 кодовых точек (32 768 плоскостей) и может кодировать 2 21 кодовых точек (32 плоскости), даже если ограничена 4 байтами. [3] Поскольку Unicode ограничивает кодовые точки 17 плоскостями, которые могут быть закодированы с помощью UTF-16, кодовые точки выше 0x10FFFF недопустимы в UTF-8 и UTF-32.

Итак, вы можете видеть, что вы можете помещать в UTF-8 что-то, что не является допустимым Unicode. Зачем? Потому что UTF-8 поддерживает кодовые точки, которые даже не поддерживает Unicode.

UTF-8, даже с четырехбайтовым ограничением, поддерживает 2 21 кодовых точек, что намного больше, чем17 * 2^16


19

2164864 «символа» потенциально могут быть закодированы с помощью UTF-8.

Это число 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21, что зависит от способа работы кодировки:

  • 1-байтовые символы имеют 7 бит для кодирования 0xxxxxxx(0x00-0x7F)

  • 2-байтовые символы имеют 11 бит для кодирования 110xxxxx 10xxxxxx(0xC0-0xDF для первого байта; 0x80-0xBF для второго)

  • 3-байтовые символы имеют 16 бит для кодирования 1110xxxx 10xxxxxx 10xxxxxx(0xE0-0xEF для первого байта; 0x80-0xBF для байтов продолжения)

  • 4-байтовые символы имеют 21 бит для кодирования 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(0xF0-0xF7 для первого байта; 0x80-0xBF для байтов продолжения)

Как видите, это значительно больше, чем текущий Unicode (1112 064 символа).

ОБНОВИТЬ

Мой первоначальный расчет неверен, потому что он не учитывает дополнительные правила. См. Комментарии к этому ответу для более подробной информации.


2
Ваша математика не соблюдает правило UTF-8, согласно которому только самая короткая последовательность кодовых единиц может кодировать кодовую точку. Итак, 00000001 действителен для U + 0001, а 11110000 10000000 10000000 10000001 - нет. Ссылка: Таблица 3-7. Хорошо сформированные байтовые последовательности UTF-8 . Кроме того, на вопрос прямо отвечает таблица: вы просто складываете диапазоны. (Они не пересекаются, чтобы исключить суррогаты для UTF-16).
Том Блоджет

Том - спасибо за комментарий! Я не знал об этих ограничениях. Я просмотрел таблицу 3-7 и проверил числа, и похоже, что существует 1 083 392 возможных действительных последовательности.
Рубен Рейес

6

UTF-8 - это кодировка переменной длины с минимум 8 битами на символ.
Символы с более высоким кодом занимают до 32 бит.


2
Это заблуждение. Самая длинная кодовая точка, которую вы можете иметь, составляет 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx, поэтому для кодирования фактического символа можно использовать только 21 бит.
Борис

5
Я сказал, что кодовые точки могут занимать до 32 бит для кодирования, я никогда не утверждал, что (по индукции) вы можете кодировать 2 ^ 32 символа в 32-битном UTF-8. Но это довольно спорный вопрос, поскольку вы можете кодировать все существующие символы Unicode в UTF-8, и вы можете кодировать еще больше, если вы растянете UTF-8 до 48 бит (который существует, но устарел), поэтому я не уверен, что заблуждение.
deceze

4

Цитата из Википедии: «UTF-8 кодирует каждую из 1112 064 кодовых точек в наборе символов Unicode, используя от одного до четырех 8-битных байтов (называемых« октетами »в стандарте Unicode)».

Некоторые ссылки:


2

Ознакомьтесь со стандартом Unicode и связанной с ним информацией, например, их часто задаваемыми вопросами, UTF-8, UTF-16, UTF-32 и BOM . Это не так гладко, но это авторитетная информация, и многое из того, что вы могли прочитать о UTF-8 в других местах, вызывает сомнения.

«8» в «UTF-8» относится к длине кодовых единиц в битах. Единицы кода - это объекты, которые используются для кодирования символов, не обязательно в виде простого взаимно-однозначного сопоставления. UTF-8 использует переменное количество кодовых единиц для кодирования символа.

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


1

Хотя я согласен с mpen в отношении текущих максимальных кодов UTF-8 (2164864) (перечисленных ниже, я не мог прокомментировать его), он отключится на 2 уровня, если вы удалите 2 основных ограничения UTF-8: только 4 байта limit и коды 254 и 255 использовать нельзя (он только убрал ограничение в 4 байта).

Начальный код 254 следует базовому расположению стартовых битов (многобитовый флаг установлен на 1, счет 6 единиц и терминал 0, нет запасных битов), что дает вам 6 дополнительных байтов для работы (6 групп 10xxxxxx, дополнительные 2 ^ 36 кодов).

Начальный код 255 не совсем соответствует базовой настройке, нет терминала 0, но используются все биты, что дает вам 7 дополнительных байтов (многобитовый флаг установлен на 1, счетчик 7 единиц и нет терминала 0, потому что используются все биты ; 7 групп 10xxxxxx, дополнительно 2 ^ 42 кода).

Их сложение дает окончательный максимально презентабельный набор символов - 4 468 982 745 216 символов. Это больше, чем все символы, которые используются в настоящее время, старые или мертвые языки, а также любые утраченные языки. Ангельский или небесный сценарий?

Также есть однобайтовые коды, которые игнорируются / игнорируются в стандарте UTF-8 в дополнение к 254 и 255: 128-191 и некоторым другим. Некоторые из них используются локально клавиатурой, пример кода 128 обычно является удаляющим backspace. Другие начальные коды (и связанные с ними диапазоны) недействительны по одной или нескольким причинам ( https://en.wikipedia.org/wiki/UTF-8#Invalid_byte_sequences ).


0

Юникод неразрывно связан с UTF-8. Unicode, в частности, поддерживает кодовые точки 2 ^ 21 (2097152 символа), что является точно таким же количеством кодовых точек, которые поддерживает UTF-8. Обе системы резервируют одно и то же «мертвое» пространство и зоны ограниченного доступа для кодовых точек и т. Д. ... по состоянию на июнь 2018 года самая последняя версия Unicode 11.0 содержит набор из 137 439 символов.

Из стандарта юникода. Unicode FAQ

Стандарт Unicode кодирует символы в диапазоне U + 0000..U + 10FFFF, который составляет 21-битное кодовое пространство.

Со страницы Википедии UTF-8. Описание UTF-8

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


21 бит округляется в большую сторону. Юникод поддерживает 1,114,112 кодовых точек (от U + 0000 до U + 10FFFF), как говорится. (Иногда описывается как 17 самолетов из 65536.)
Том Блоджет

@TomBlodget, Вы правы. Наиболее важный вывод из этого обсуждения заключается в том, что UTF-8 может кодировать все точки, определенные в настоящее время в стандарте Unicode, и, вероятно, сможет это делать в течение некоторого времени.
Отображаемое имя
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.