Скільки байтів займає один символ Unicode?


239

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

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

А що означають UTF-7, UTF-6, UTF-16 тощо? Це різні версії Unicode?

Я читав статтю Вікіпедії про Unicode, але мені це досить важко. Я з нетерпінням чекаю простої відповіді.



15
Вибачте, немає простої відповіді. Я знаходжу всю справу трохи безладно. Unicode виставляли рахунок як використання двох байтів і вміння представляти всі символи, але, виявляється, двох байтів було недостатньо.
Джонатан Вуд

12
"Проста відповідь": Унікод символу займає 1-4 байти. Unicode охоплює багато мов, але не всі. Востаннє я дивився, наприклад, Клінгон не був офіційним набором символів Unicode.
Петро Г.

9
Klingon не є частиною самого стандарту Unicode, ні. Замість нього використовується область приватного користування Uniode (U + F8D0 - U + F8FF).
Ремі Лебо

1
Питання рятівника - спасибі. Моя ситуація - це зберігання даних через сумісні з LMS-файлами SCORM 1.2 ... стандарт для SCORM 1.2 'cmi.suspend_data' - це 4096 байт даних, які попередній розробник припускав, що ми можемо зберігати 4096 символів. Ой, людина помилявся - я щойно виявив, чому наша закладка не працює на довгих курсах. Тож тепер я знаю, оскільки ми використовуємо UTF-8, він займає 4 байти на символ, що дає нам 1024 символи.
danjah

Відповіді:


147

Ви не побачите простої відповіді, оскільки такої немає.

По-перше, Unicode не містить "кожного символу з кожної мови", хоча він, безумовно, намагається.

Unicode сам по собі є відображенням, він визначає кодові точки, а кодова точка - це число, пов'язане зазвичай з символом. Я кажу, що зазвичай є такі поняття, як поєднання символів. Можливо, ви знайомі з такими речами, як акценти чи умулати. Вони можуть бути використані з іншим символом, наприклад, a aабо uдля створення нового логічного символу. Отже, символ може складатися з 1 або більше точок коду.

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

Через гнучкість поєднання символів навіть у межах заданого кодування кількість байтів на символ може змінюватись залежно від символу та форми нормалізації. Це протокол для роботи з символами, які мають більше ніж одне представлення (можна сказати, "an 'a' with an accent"що це 2 кодові точки, одна з яких - об'єднана знака або "accented 'a'"одна кодова точка).


1
ГАРАЗД. Тоді скільки байтів займає один заданий символ, представлений в одній заданій кодовій точці? Наприклад, нерозривний простір.
Ніколя Барбулеско

Об'єднані символи роблять життя програміста пекельним, коли мова йде про написання strlen (), substr () та інших функцій маніпулювання рядками на масивах UTF8. Така робота ніколи не буде повноцінною і завжди баггі.
Нулик

Я написав демонстраційну версію, яка показує файли, кодовані Windows-1252, UTF8 та UTF8-BOM, що інтерпретуються з кожним кодуванням, і порівнює рівність між результатами: github.com/vladyrn/encodings_demo
Влад

195

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

Binary    Hex          Comments
0xxxxxxx  0x00..0x7F   Only byte of a 1-byte character encoding
10xxxxxx  0x80..0xBF   Continuation byte: one of 1-3 bytes following the first
110xxxxx  0xC0..0xDF   First byte of a 2-byte character encoding
1110xxxx  0xE0..0xEF   First byte of a 3-byte character encoding
11110xxx  0xF0..0xF7   First byte of a 4-byte character encoding

Отже, швидка відповідь: це займає від 1 до 4 байтів, залежно від першого, який вказуватиме, скільки байтів він займе.


8
Я вважаю, що максимальне значення Hex для 4-байтового символу - 0xF7 (не 0xF4).
DJPJ

Дуже дякую! Я просто контролював + перебирав стандарт IETF, і про кодування нічого не знайшов, і стаття, яку я читав, не вдавалася досить детально, щоб сказати, скільки біт використовується для представлення кількості трейлінг-коду бали за "символ".
MarcusJ

1
Це тепер на другій сторінці мого шпаргалки "Вступ для нових членів команди", а також веселі перші два коментарі
Cee McSharpface

1
0xF4 не була помилкою, а уточненням. Кодові точки Unicode знаходяться в діапазоні 0-0x10ffff, тому остання кодова точка кодується як F4 8F BF BF.
Frediano Ziglio

38

Я знаю, що це питання давнє і вже має прийняту відповідь, але я хочу запропонувати кілька прикладів (сподіваючись, що комусь це стане в нагоді).

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

Правильно. Насправді, оскільки ASCII - це 7-бітове кодування, він підтримує 128 кодів (95 з яких можна друкувати), тому він використовує лише половину байтів (якщо це має сенс).

Скільки байтів вимагає символ Unicode?

Unicode просто відображає символи в кодових точках. Це не визначає, як їх кодувати. Текстовий файл містить не символи Unicode, а байти / октети, які можуть представляти символи Unicode.

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

Ні, але майже. Так в основному так. Але все одно ні.

Так скільки байтів потрібно на один символ?

Те саме, що і ваше друге запитання.

А що означають UTF-7, UTF-6, UTF-16 тощо? Це якісь версії Unicode?

Ні, це кодування. Вони визначають, як байти / октети повинні представляти символи Unicode.

Пара прикладів. Якщо деякі з них неможливо відобразити у вашому браузері (можливо, тому, що шрифт не підтримує їх), перейдіть до 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 EURO Знак:
      • Nº: 8364
      • UTF-8: E2 82 AC
      • UTF-16: 20 змінного струму
    • U + 2122 ЗНАЧЕННЯ ТОРГОВОЇ МАРКИ:
      • Nº: 8482
      • UTF-8: E2 84 A2
      • UTF-16: 21 22
    • 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 UMBRELLA З дощовими краплями:
      • 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 PILE POO: 💩
      • Nº: 128169
      • UTF-8: F0 9F 92 A9
      • UTF-16: D8 3D DC A9
    • U + 1F680 ROCKET: 🚀
      • Nº: 128640
      • UTF-8: F0 9F 9A 80
      • UTF-16: D8 3D DE 80

Гаразд, я захоплююся ...

Цікаві факти:


У блоки коду в UTF-16 в 16 біт. Ви показали їм пробіл посередині, який вводить в оману. Представлення UTF-16 для © має бути 00A9замість 00 A9(що було б UTF-16BE).
Roland Illig

Яка різниця? Хіба НЕ означає великого ендіана? Він написав його великим ендіаном, і тому файл, написаний великим ендіаном UTF-16, був би таким самим, як UTF-16BE, правда?
HappyPandaFace

6
Виправлення: 1) ASCII - це 7 біт, байт - 8 біт, так що це набагато більше половини. 2) Unicode визначає, як кодувати точки коду. UTF-8, UTF-16 і UTF-32 визначені в стандарті Unicode.
Джонатан Розенн

3
@JonathanRosenne Я думаю, що він / він мав на увазі, що він використовує лише половину можливих значень, представлених 8 бітами, не те, що він використовує половину бітів.
Аріц Лопес

2
Мені дуже подобаються приклади. Вони підкреслюють, чому, наприклад, можна віддати перевагу UTF-16 перед UTF-8. Розробники іншого програмного забезпечення можуть вибирати різні кодування, на основі яких більше шансів використовувати символи Unicode. Наприклад, у Китаї / Японії UTF-16 (2-байт) має для них більше сенсу, ніж UTF-8, тому що для одних і тих же символів для кодування в UTF-8 часто потрібно два рази більше байтів
Майк

29

Простіше кажучи Unicode, це стандарт, який присвоїв одне число (зване кодовою точкою) всім персонажам світу (його все ще працює).

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

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

UTF-32 кожен символ має 4 байти символів.

UTF-16використовує 16 біт для кожного символу, і він представляє лише частину символів Unicode під назвою BMP (для всіх практичних цілей достатньо). Java використовує це кодування у своїх рядках.


10
Unicode - це 21-бітний набір коду, і 4 байти достатньо, щоб представити будь-який символ Unicode в UTF-8. UTF-16 використовує сурогати для представлення символів поза BMP (основна багатомовна площина); для представлення будь-якого дійсного символу Unicode йому потрібно 2 або 4 байти. UCS-2 був єдиним 16-розрядним варіантом UTF-16 без підтримки сурогатів або символів поза BMP.
Джонатан Леффлер

1
Ви праві. Оригінальний UTF-8 мав 6 байт, щоб вмістити 32-бітний. Я насправді не хотів сильно ускладнювати речі, оскільки його вже плутали з wiki doc :)
Зімбабао

3
У цій відповіді зазначено, що UTF-16 не може кодувати BMP-точки. Це неправильно, оскільки вони можуть бути закодовані так само, як вони можуть бути в UTF-8, використовуючи сурогатні пари. (Ви повинні думати про застарілий UCS-2, перш ніж вийшов Unicode 2.0, який кодував лише 16-бітові кодові точки.) Також Java не зовсім використовує UTF-16, вона використовує модифіковану форму її, де точка коду 0 кодується по-різному.
rdb

@rdb - це навпаки. Відповідь говорить, що UTF-16 являє собою BMP.
Ніколя Барбулеско

3
Я неправильно вводив; Я мав намір сказати "не БМП". Помилка у відповіді полягає в тому, що вона говорить про те, що UTF-16 представляє символи BMP, що є неточним. UTF-16 може кодувати всі символи unicode-- символи, що не є BMP, кодуються через сурогатні пари. Можливо, відповідач був переплутаний з UCS-2.
rdb

17

У 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 є останньою кодовою точкою унікоду за визначенням, і вона визначена таким чином, оскільки це технічна межа UTF-16.

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


8

У Unicode відповідь не дається легко. Проблема, як ви вже вказали, - це кодування.

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

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

Що робить це так важко - це принаймні дві речі:

  1. складені символи, де замість того, щоб використовувати сутність символів, яка вже наголошена / діакритична (À), користувач вирішив поєднати акцент і базовий символ (`A).
  2. кодові пункти. Точки коду - це метод, за допомогою якого кодування UTF дозволяють кодувати більше, ніж кількість бітів, що дає їм їх ім'я, як правило, дозволяє. Напр., UTF-8 позначає певні байти, які самі по собі є недійсними, але після цього дійсний байт продовження дозволить описати символ за межами 8-бітового діапазону 0..255. Дивіться приклади та надмірні кодування нижче у статті Вікіпедії на UTF-8.
    • Відмінний приклад, що наводиться там, полягає в тому, що символ € (кодова точка U+20ACможе бути представлена ​​або як трибайтова послідовність, E2 82 ACабо чотирибайтова послідовністьF0 82 82 AC .
    • Обидва є дійсними, і це показує, наскільки складною є відповідь, коли йдеться про "Unicode", а не про конкретне кодування Unicode, наприклад UTF-8 або UTF-16.


4

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

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

Тож ваша проста відповідь, яку ви хочете, полягає в тому, що вона змінюється.


3

Для UTF-16 символу потрібно чотири байти (два кодові одиниці), якщо він починається з 0xD800 або більше; такого персонажа називають "сурогатною парою". Більш конкретно, сурогатна пара має форму:

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

де [...] вказує двобайтовий блок коду із заданим діапазоном. Що-небудь <= 0xD7FF - це одна одиниця коду (два байти). Що-небудь> = 0xE000 недійсне (крім маркерів BOM, можливо).

Див. Http://unicodebook.readthedocs.io/unicode_encodings.html , розділ 7.5.



1

З Вікі:

UTF-8, 8-бітове кодування змінної ширини, що забезпечує максимальну сумісність з ASCII;

UTF-16, 16-бітове кодування змінної ширини;

UTF-32, 32-бітове кодування з фіксованою шириною.

Це три найпопулярніші різні кодування.

  • У UTF-8 кожен символ кодується в 1 - 4 байти (домінантне кодування)
  • У UTF16 кожен символ кодується в 1 до двох 16-бітних слів і
  • в UTF-32 кожен символ кодується як одне 32-бітове слово.

1

Unicodeце стандарт, який забезпечує унікальний номер для кожного персонажа. Ці унікальні номери називаються code points (що є просто унікальним кодом) для всіх символів, що існують у світі (деякі ще потрібно додати).

Для різних цілей вам може знадобитися представити це code pointsв байтах (більшість мов програмування це роблять), і ось де Character Encodingпочинається.

UTF-8, UTF-16, UTF-32І так далі все Character Encodings, і кодові точки в наборах Unicode представлені в цих кодуваннях, по - різному.


UTF-8 кодування має змінну ширину довжини, і символи, закодовані в ньому, можуть займати від 1 до 4 байтів включно;

UTF-16має змінну довжину і символи, закодовані в ньому, можуть приймати або 1, або 2 байти (що становить 8 або 16 біт). Це представляє лише частину всіх символів Unicode під назвою BMP (Basic Multilingual Plane), і цього вистачає майже для всіх випадків. Java використовує UTF-16кодування для своїх рядків і символів;

UTF-32 має фіксовану довжину і кожен символ займає рівно 4 байти (32 біта).

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