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


97

Якщо UTF-8 має 8 біт, чи не означає це, що може бути максимум 256 різних символів?

Перші 128 кодових точок такі ж, як і в ASCII. Але там сказано, що UTF-8 може підтримувати до мільйона символів?

Як це працює?


2
якщо б ви могли переоцінити це питання, оскільки всі відповіді неправильні. Прочитайте мою відповідь: stackoverflow.com/a/45042566/124486
Еван Керролл,

У кодуваннях UTF-8, UTF-16, UTF-32 Unicode числом є кількість бітів у його кодових одиницях , одна або кілька з яких кодують кодову точку Unicode.
Tom Blodget

1
Я відповів на це запитання деякий час тому, намагаючись це виправити: було б чудово, якби ви зважили його проти обраної відповіді, яка є буквально просто однією цитатою з Вікіпедії, яка не розповідає всієї історії (сподіваюся, моє оновлення набагато чіткіше)
Еван Керролл,

Відповіді:


135

UTF-8 не використовує постійно один байт, це 1-4 байти.

Перші 128 символів (US-ASCII) потребують одного байта.

Наступним 1920 символам для кодування потрібно два байти. Це охоплює решту майже всіх латинських алфавітів, а також грецький, кириличний, коптський, вірменський, іврит, арабський, сирійський та танський алфавіти, а також поєднання діакритичних знаків.

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

Чотири байти потрібні для символів в інших площинах Unicode, які включають менш поширені символи CJK, різні історичні сценарії, математичні символи та смайли (піктографічні символи).

джерело: Вікіпедія


привіт @zwippie я новачок у цьому. Щось я не розумію.! BMP використовує 2 байти, які, на вашу думку, дорівнюють 3? я помиляюся?
chiperortiz

1
@chiperortiz, BMP насправді становить 16 біт, тому його можна кодувати як UTF-16 з постійною довжиною на символ (UTF-16 також підтримує перевищення 16 біт, але це складна практика, і багато реалізацій не підтримують цього). Однак для UTF-8 вам також потрібно закодувати, скільки часу це буде, тому ви втратите трохи бітів. Ось чому вам потрібно 3 байти для кодування повного BMP. Це може здатися марним, але пам’ятайте, що UTF-16 завжди використовує 2 байти, але UTF-8 використовує по одному байту на символ для більшості символів мови на основі латиниці. Робимо його вдвічі компактнішим.
sanderd17

Основна спрямованість запитання OP пов'язана з тим, чому його називають UTF- 8 - це насправді не відповідає на це.
jbyrd

39

UTF-8 використовує 1-4 байта на символ: один байт для символів ascii (перші 128 значень Unicode такі самі, як ascii). Але для цього потрібно лише 7 біт. Якщо встановлено найвищий біт ("знак"), це вказує на початок багатобайтової послідовності; кількість послідовних встановлених старших бітів вказує кількість байтів, потім 0, а решта бітів вносять значення. Для інших байтів два найвищі біти становитимуть 1 і 0, а решта 6 бітів - для значення.

Отже, послідовність із чотирьох байт починається з 11110 ... (і ... = три біти для значення), потім три байти з 6 бітами для кожного, отримуючи 21-бітове значення. 2 ^ 21 перевищує кількість символів Unicode, тому весь Unicode може бути виражений в UTF8.


@NickL. Ні, я маю на увазі 3 байти. У цьому прикладі, якщо перший байт послідовності багатобайтові починається 1111, перший 1 вказує на те, що це початок послідовності багатобайтові, то число послідовних 1 після того, як, що вказує число додаткових байтів в послідовності (так що перший байт почнеться або 110, 1110, або 11110).
CodeClown42

Знайшов доказ для своїх слів у 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,

Я здогадуюсь, що NickL запитав це, але що сталося з рештою бітів у цьому першому байті, якщо ... представляє наступні байти замість бітів?
c6754,

26

Відповідно до цієї таблиці * UTF-8 повинен підтримувати:

2 31 = 147 483 688 символів

Однак RFC 3629 обмежив можливі значення, тому зараз ми обмежуємося 4 байтами , що дає нам

2 21 = 2097152 символів

Зверніть увагу, що велика частина цих символів "зарезервована" для користувальницького використання, що насправді дуже зручно для шрифтів значків.

* У використаній Вікіпедії показано таблицю з 6 байтами - з тих пір вони оновили статтю.

11.07.2017: Виправлено для подвійного підрахунку тієї самої кодової точки, кодованої кількома байтами


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

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

@mpen, який код 00000001зберігається, а що 11000000 100000001зберігається?
Еван Керролл,

1
@EvanCarroll Uhh .... отримано очко. Не розумів, що існує кілька способів кодування однієї і тієї ж кодової точки.
mpen

1
Я спробував відповісти на це сам, подивіться, чи вважаєте ви, що це краще пояснення та відповідь на запитання: stackoverflow.com/a/45042566/124486
Еван Керролл,

21

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

Юнікод вирішує кодові точки до символів. UTF-8 - це механізм зберігання для Unicode. Unicode має специфікацію. UTF-8 має специфікацію. Вони обидва мають різні межі. UTF-8 має інший висхідний сигнал.

Unicode

Unicode позначається "площинами". Кожна площина несе 2 16 кодових точок. У Unicode є 17 літаків. Для загальної кількості 17 * 2^16кодових балів. Перша площина, площина 0 або BMP , є особливою в вазі , що він несе.

Замість того, щоб пояснювати всі нюанси, дозвольте мені просто процитувати вищевказану статтю про літаки.

17 літаків можуть вмістити 1114112 кодових точок. З них 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, навіть з обмеженням у чотири байти, підтримує 22 кодових точки, що набагато більше17 * 2^16


18

2164864 "символи" можуть бути потенційно закодовані UTF-8.

Це число 2 ^ 7 + 2 ^ 11 + 2 ^ 16 + 2 ^ 21, що походить від способу роботи кодування:

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

  • Двобайтові символи мають 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).
Tom Blodget

Томе - дякую за ваш коментар! Я не знав про ці обмеження. Я побачив таблицю 3-7 і провів цифри, і, схоже, існує 1083 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 бітів (що існує, але застаріло), тому я не впевнений, що оманливим моментом є.
обдурити

3

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

Деякі посилання:


2

Ознайомтеся зі стандартом Unicode та пов’язаною інформацією, такою як запитання щодо часто заданих питань, UTF-8 UTF-16, UTF-32 та специфікація . Це не настільки плавне плавання, але це достовірна інформація, і багато з того, що ви могли прочитати про 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 1 і термінал 0, без запасних бітів), що дає вам 6 додаткових байтів для роботи (6 груп 10xxxxxx, додаткові 2 ^ 36 кодів).

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

Додаючи їх у, ви отримаєте остаточний максимальний презентабельний набір символів - 4 468 982 745 216. Це більше, ніж усі символи, які зараз використовуються, старі або мертві мови та будь-які втрачені мови. Ангельський чи Небесний сценарій хтось?

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


0

Юнікод міцно одружений на UTF-8. Юнікод спеціально підтримує 2 ^ 21 кодових точок (2 097 152 символів), що є точно такою ж кількістю кодових точок, що підтримується UTF-8. Обидві системи резервують однаковий "мертвий" простір та зони обмеженого доступу для кодових точок тощо ... станом на червень 2018 року остання версія Unicode 11.0 містить репертуар із 137 439 символів

Зі стандарту Unicode. Поширені запитання про Unicode

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

Зі сторінки UTF-8 у Вікіпедії. UTF-8 Опис

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


21 біт округлюється. Unicode підтримує 1114112 кодових точок (U + 0000 до U + 10FFFF), як сказано. (Іноді описується як 17 літаків 65536.)
Том Блоджет,

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