Яка максимальна кількість байтів для кодованого символу UTF-8?


79

Яка максимальна кількість байтів для одного кодованого символу UTF-8?

Я буду шифрувати байти рядка, закодованого в UTF-8, і тому мені потрібно мати можливість визначити максимальну кількість байтів для кодованого рядка UTF-8.

Хтось може підтвердити максимальну кількість байтів для одного кодованого символу UTF-8, будь ласка


1
Ви зробили погляд на загальні ресурси, такі як Вікіпедії UTF-8 статті , перший ... НЕ так?

5
Я прочитав декілька статей, які давали неоднозначні відповіді ... Насправді у мене склалося враження, що відповідь була 3, тому я дуже радий, що запитав
Едд,

2
Я залишу тут посилання на YouTube із персонажами Тома Скотта, символами, дивом Unicode: goo.gl/sUr1Hf . Ви можете почути і побачити, як все еволюціонувало від кодування символів ASCII до utf-8.
Рой Лі,

Див. Також Розрахунок довжини в UTF-8 Java String без фактичного кодування для прикладу обчислень довжини
Вадзім

Відповіді:


86

Максимальна кількість байтів на символ - 4 відповідно до RFC3629 який обмежив таблицю символів U+10FFFF:

В UTF-8 символи з діапазону U + 0000..U + 10FFFF (доступний діапазон UTF-16) кодуються з використанням послідовностей від 1 до 4 октетів.

(Оригінальна специфікація допускала до шести байт-кодів символів для минулих кодових точок U+10FFFF .)

Для символів із кодом менше 128 потрібно лише 1 байт, а для наступних 1920 символів - лише 2 байти. Якщо ви не працюєте з езотеричною мовою, множення кількості символів на 4 буде значним завищенням.


7
Що для вас "езотерична мова"? Будь-яка мова, яка існувала б у реальному світі, або текст, який перемикається між різними мовами світу? Чи повинен розробник функції UTF-8-to-String вибрати мультиплікатор 2, 3 або 4, якщо він робить перерозподіл і зменшує результат після фактичного перетворення?
Даніель Маршалл,

1
@rinntech під "езотеричною мовою" він означає мову, яка має багато значних символів Unicode (щось приблизно внизу цього списку: unicode-table.com/en/sections ). Якщо вам потрібно перерозподілити, оберіть 4. Ви можете зробити подвійний прохід, один, щоб побачити, скільки байтів вам знадобиться і виділити, а інший - для кодування; це може бути краще, ніж виділити ~ 4 рази необхідної оперативної пам'яті.
matiu

9
Завжди намагайтеся розглянути найгірший випадок: hacker9.com/single-message-can-crash-whatsapp.html
Євген Бодунов

20
Символи CJKV в основному займають 3 байти (деякі рідкісні / архаїчні символи займають 4 байти), і називати їх езотеричними трохи розтягується (лише Китай складає майже 20% населення світу ...).
Tgr

3
Чому його обмежили 4, коли раніше було 6? Що заважає нам продовжувати стандарт і мати провідний байт 11111111і мати 2^(6*7)трохи місця для символів?
Аарон Франке,

32

Без подальшого контексту я б сказав, що максимальна кількість байт для символу в UTF-8 становить

відповідь: 6 байт

Автор прийнятої відповіді правильно вказав це як "оригінальну специфікацію". Це було дійсним згідно з RFC-2279 1 . Як зазначив Дж. Коко в коментарях нижче, це змінилося в 2003 р. З RFC-3629 2 , який обмежує UTF-8 кодуванням для 21 біта, яке можна обробляти за допомогою схеми кодування за допомогою чотирьох байтів.

відповідь, якщо охоплює всі Unicode: 4 байти

Але в Java <= v7 вони говорять про 3-байтовий максимум для представлення Unicode з UTF-8? Це тому, що оригінальна специфікація Unicode визначала лише базову багатомовну площину ( BMP ), тобто це старіша версія unicode або підмножина сучасного unicode. Так

відповідь, якщо він представляє лише оригінальний унікод, BMP: 3 байти

Але ОП говорить про те, щоб піти іншим шляхом. Не від символів до байтів UTF-8, а від байтів UTF-8 до "рядка" подання байтів. Можливо, автор прийнятої відповіді отримав це з контексту запитання, але це не обов'язково очевидно, тому може заплутати випадкового читача цього питання.

Переходячи від UTF-8 до власного кодування, ми повинні поглянути на те, як реалізовано "Рядок". Деякі мови, наприклад Python> = 3, представлятимуть кожен символ із цілочисельними кодовими точками, що дозволяє 4 байти на символ = 32 біти, щоб покрити 21, необхідний нам для Unicode, з деякими витратами. Чому не саме 21 біт? Тому що все відбувається швидше, коли вони вирівняні за байтами. Деякі мови, такі як Python <= 2 та Java, представляють символи з використанням кодування UTF-16, що означає, що вони повинні використовувати сурогатні пари для представлення розширеного Unicode (не BMP). У будь-якому випадку це все ще максимум 4 байти.

відповідь, якщо йде UTF-8 -> власне кодування: 4 байти

Отже, остаточний висновок 4 - найпоширеніша правильна відповідь, отже, ми правильно зрозуміли. Але, пробіг може варіюватися.


5
"це все ще поточна та правильна специфікація, згідно з wikipedia" - не більше. Незабаром після того, як ви написали це (редагування 2 квітня), статтю Вікіпедії UTF-8 було змінено, щоб пояснити, що 6-октетна версія не є частиною поточної специфікації (2003) UTF-8.
Дж. Коко,

"Але в Java <= v7 вони говорять про 3-байтовий максимум для представлення Unicode з UTF-8? Це тому, що оригінальна специфікація Unicode визначала лише базову багатомовну площину" - Це, мабуть, первісна причина, але це не вся історія. Java використовує "модифікований UTF-8", і одна з модифікацій полягає в тому, що він "використовує власний двократно-трибайтовий формат" замість "чотирибайтовий формат стандартного UTF-8" (їх слова).
Дж. Коко,

1
Немає кодових точок, виділених вище обмеження 10FFFF (трохи більше мільйона), і багато реалізацій UTF8 ніколи не реалізовували послідовності довше 4 байт (а деякі лише 3, наприклад MySQL), тому я вважаю безпечним жорстке обмеження до 4 байт на codepoint навіть при розгляді питання сумісності зі старими реалізаціями. Вам просто потрібно переконатися, що ви відкидаєте все недійсне на шляху. Зверніть увагу, що рекомендація matiu щодо розподілу після обчислення точної довжини байтів є гарною, де це можливо.
thomasrutter

2
"... Нікод [U] може представляти до кодових точок x10FFFF. Отже, включаючи 0, це означає, що ми можемо зробити це з цими байтами: F FF FF, тобто два з половиною байти, або 20 бітів." Я вважаю, що це трохи неправильно. Кількість кодових точок від 0x0 до 0x10FFFF буде 0x110000, яке може бути представлене в 1F FF FF, або 21 біт. Число 0x110000 відповідає 17 площинам кодових точок 0x10000 кожна.
neuralmer

2
PSA: Вікіпедія не є справжнім джерелом. Подивіться на фактичні посилання на статтю.
Nyerguds

0

Максимальна кількість байт для підтримки US-ASCII, стандартного кодування англійського алфавіту, дорівнює 1. Але обмеження тексту англійською мовою з часом стає менш бажаним або практичним.

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

Хоча максимальна кількість байт на символ UTF-8 становить 3 для підтримки лише 2-байтового адресного простору площини 0, Базової багатомовної площини (BMP), яка може бути прийнята як мінімальна підтримка в деяких додатках, вона становить 4 для підтримки усі 17 поточних літаків Unicode (станом на 2019 рік). Слід зазначити, що багато популярних символів "смайликів", ймовірно, знаходяться в площині 16, для якої потрібно 4 байти.

Однак це стосується лише основних гліфів. Існують також різні модифікатори, такі як наголошення над попереднім символом, а також можна зв'язати довільну кількість кодових точок для побудови однієї складної "графеми". Отже, у реальному програмуванні використання або припущення про встановлену максимальну кількість байтів на символ, зрештою, може призвести до проблеми у вашому додатку.

З цих міркувань випливає, що рядки символів UTF-8 не повинні "розширюватися" до масивів фіксованої довжини перед обробкою, як це іноді робили. Натомість програмування слід здійснювати безпосередньо, використовуючи рядкові функції, спеціально розроблені для UTF-8.


Примітка: абзац про невикористання масиву символів фіксованої ширини - це моя власна думка. Я готовий відредагувати цю відповідь у відповідь на коментарі.
Девід Спектор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.