Що таке Unicode, UTF-8, UTF-16?


395

Що є основою для Unicode і чому необхідність UTF-8 або UTF-16? Я досліджував це в Google і шукав і тут, але мені це не зрозуміло.

У VSS під час порівняння файлів іноді виникає повідомлення про те, що два файли мають різні UTF. Чому це було б так?

Будь ласка, поясніть простими словами.



5
Цей FAQ на офіційному веб-сайті Unicode пропонує відповіді для вас.
Неманья Трифунович

4
@John: це дуже приємне вступ, але це не остаточне джерело: воно пропускає досить багато деталей (що чудово для огляду / вступу!)
Йоахім Зауер

5
Стаття чудова, але вона має кілька помилок і представляє UTF-8 у дещо консервативному світлі. Я пропоную прочитати utf8everywhere.org як додаток.
Павло Радзівіловський

2
Погляньте на цей веб-сайт: utf8everywhere.org
Vertexwahn

Відповіді:


550

Навіщо нам потрібен Unicode?

У (не надто) ранні дні все, що існувало, було ASCII. Це було нормально, оскільки все, що коли-небудь знадобилося, - це кілька контрольних символів, пунктуації, цифри та букви, як у цьому реченні. На жаль, сьогоднішній дивний світ глобальної взаємодії та соціальних медіа не передбачався, і не надто незвично в цьому ж документі бачити англійську, українську, іспанську, ελληνικά та ((сподіваюся, я не зламав жодного старого браузери).

Але заради аргументу, скажімо, Джо Середній - розробник програмного забезпечення. Він наполягає на тому, що йому буде потрібно лише коли-небудь англійська мова, і як такий хоче лише використовувати ASCII. Це може бути добре для Джо користувача , але це не добре для Джо розробника програмного забезпечення . Приблизно половина світу використовує не латинські символи, і використання ASCII є, мабуть, неуважним до цих людей, і, крім того, він закриває своє програмне забезпечення для великої та зростаючої економіки.

Тому необхідний набір символів, що включає всі мови. Так вийшов Unicode. Він присвоює кожному символу унікальне число, яке називається кодовою точкою . Однією з переваг Unicode перед іншими можливими наборами є те, що перші 256 кодових точок ідентичні ISO-8859-1 , а отже, і ASCII. Крім того, переважна більшість символів, що часто використовуються, представлені лише двома байтами в області, що називається базовою багатомовною площиною (BMP) . Тепер кодування символів потрібне для доступу до цього набору символів, і, як задається питанням, я сконцентруюся на UTF-8 та UTF-16.

Міркування щодо пам'яті

Отже, скільки байтів надають доступ до тих символів у цих кодуваннях?

  • UTF-8:
    • 1 байт: Стандарт ASCII
    • 2 байти: арабська, іврит, більшість європейських сценаріїв (найбільш винятково грузинська )
    • 3 байти: BMP
    • 4 байти: Усі символи Unicode
  • UTF-16:
    • 2 байти: BMP
    • 4 байти: Усі символи Unicode

Зараз варто згадати, що символи, які не входять до BMP, включають стародавні сценарії, математичні символи, музичні символи та рідші китайські / японські / корейські символи.

Якщо ви будете працювати в основному з символами ASCII, то UTF-8, безумовно, ефективніше пам'яті. Однак, якщо ви працюєте в основному з неєвропейськими сценаріями, використання UTF-8 може бути в 1,5 рази менш ефективною пам'яттю, ніж UTF-16. У роботі з великою кількістю тексту, наприклад, великими веб-сторінками або довгими текстовими документами, це може вплинути на ефективність роботи.

Основи кодування

Примітка. Якщо ви знаєте, як кодуються UTF-8 та UTF-16, перейдіть до наступного розділу для практичних застосувань.

  • UTF-8: Для стандартних символів ASCII (0-127) коди UTF-8 однакові. Це робить UTF-8 ідеальним, якщо потрібна зворотна сумісність із існуючим текстом ASCII. Для інших символів потрібно десь 2-4 байти. Це робиться за допомогою резервування деяких бітів у кожному з цих байтів, щоб вказати, що він є частиною багатобайтового символу. Зокрема, перший біт кожного байту - 1це уникати зіткнення з символами ASCII.
  • UTF-16: Для дійсних символів BMP представлення UTF-16 є просто його кодовою точкою. Однак для символів, що не належать до BMP, UTF-16 вводить сурогатні пари . У цьому випадку поєднання двох двобайтових ділянок відображає характер, що не належить до BMP. Ці двобайтові ділянки походять з числового діапазону BMP, але вони гарантуються стандартом Unicode як недійсні як символи BMP. Крім того, оскільки UTF-16 має два байти в якості основної одиниці, це впливає на витривалість . Для компенсації на початку потоку даних може бути розміщений зарезервований байт порядку, який вказує на витривалість. Таким чином, якщо ви читаєте вхід UTF-16, і не вказана небезпека, ви повинні перевірити це.

Як видно, UTF-8 і UTF-16 ніде не сумісні між собою. Тому якщо ви робите I / O, переконайтеся, що ви знаєте, яке кодування ви використовуєте! Детальнішу інформацію про ці кодування див. У відповідях на поширені питання UTF .

Практичні міркування щодо програмування

Характеристика та рядкові типи даних: Як вони кодуються мовою програмування? Якщо вони є необробленими байтами, у хвилину, коли ви спробуєте вивести символи, що не належать до ASCII, у вас можуть виникнути проблеми. Крім того, навіть якщо тип символу заснований на UTF, це не означає, що рядки є належним UTF. Вони можуть дозволити незаконні послідовності байтів. Як правило, вам доведеться використовувати бібліотеку, яка підтримує UTF, наприклад ICU для C, C ++ та Java. У будь-якому випадку, якщо ви хочете ввести / вивести щось інше, ніж кодування за замовчуванням, вам доведеться спочатку перетворити це.

Рекомендовані / за замовчуванням / домінуючі кодування: Коли вибираєте, який UTF використовувати, зазвичай краще дотримуватися рекомендованих стандартів для середовища, в якому ви працюєте. Наприклад, UTF-8 є домінуючим в Інтернеті, а оскільки HTML5 - це було рекомендовано кодування . І навпаки, обидва середовища .NET і Java засновані на типі символів UTF-16. Заплутано (і неправильно) часто посилаються на "кодування Unicode", яке зазвичай посилається на домінуюче кодування UTF у заданому середовищі.

Бібліотечна підтримка: Бібліотеки, якими ви користуєтеся, підтримують якесь кодування. Який? Чи підтримують вони кутові справи? Оскільки необхідність є основою винаходу, бібліотеки UTF-8, як правило, належним чином підтримують 4-байтові символи, оскільки 1, 2 і навіть 3-байтні символи можуть траплятися часто. Однак, не всі бібліотеки UTF-16 підтримують сурогатні пари належним чином, оскільки вони трапляються дуже рідко.

Підрахунок символів: У Unicode є об'єднання символів. Наприклад, кодова точка U + 006E (n) та U + 0303 (об'єднує тильда) утворює ñ, але кодова точка U + 00F1 утворює ñ. Вони повинні виглядати однаково, але простий алгоритм підрахунку поверне 2 для першого прикладу, 1 для другого. Це не обов'язково неправильно, але це може бути і не бажаним результатом.

Порівняння рівності: A, А та Α виглядають однаково, але вони відповідно латині, кирилиці та грецькій мові. У вас також є випадки типу C і and, один - літера, а другий - римська цифра. Крім того, ми маємо враховувати і комбінуючі символи. Для отримання додаткової інформації див. Копії символів у Unicode .

Сурогатні пари: Вони з'являються досить часто на SO, тому я надам лише кілька прикладних посилань:

Інші ?:


11
Відмінна відповідь, великі шанси на винагороду ;-) Особисто я додам, що деякі аргументують UTF-8 як універсальне кодування символів , але я знаю, що це думка, яку не обов'язково поділяють усі.
Йоахім Зауер

3
На цьому етапі для мене все ще занадто технічно. Як слово привіт зберігається на комп'ютері в UTF-8 та UTF-16?
FirstName LastName

1
Чи можете ви розширити докладніше про те, чому, наприклад, BMP займає 3 байти в UTF-8? Я б подумав, що оскільки його максимальне значення становить 0xFFFF (16 біт), то для доступу до нього потрібно буде лише 2 байти.
відмітка

2
@mark Деякі біти зарезервовані для кодування. Для кодової точки, що займає 2 байти в UTF-8, є 5 зарезервованих бітів, залишаючи лише 11 біт для вибору кодової точки. U + 07FF виявляється найвищою кодовою точкою, представленою у 2 байтах.
DPenner1

1
BTW - ASCII визначає лише 128 кодових точок, використовуючи лише 7 біт для представлення. Саме ISO-8859-1 / ISO-8859-15 визначають 256 кодових точок і використовують 8 біт для представлення. Перші 128 кодових пунктів у всіх цих 3 однакові.
Tuxdude

67
  • Unicode
    • - це набір символів, які використовуються у всьому світі
  • UTF-8
    • кодування символів, здатне кодувати всі можливі символи (звані кодові точки) в Unicode.
    • одиниця коду - 8 біт
    • використовуйте від одного до чотирьох одиниць коду для кодування Unicode
    • 00100100 за " $ " (один 8-бітний); 11000010 10100010 для " ¢ " (два 8-бітні); 11100010 10000010 10101100 за " " (три 8-бітні)
  • UTF-16
    • інше кодування символів
    • одиниця коду - 16 біт
    • використовувати один-два одиниці коду для кодування Unicode
    • 00000000 00100100 за " $ " (один 16-бітний); 11011000 01010010 11011111 01100010 для " 𤭢 " (два 16-бітні)

1
Короткий і точний
Aritra Chatterjee

30

Unicode - досить складний стандарт. Не бійтеся занадто, але будьте готові до якоїсь роботи! [2]

Оскільки завжди потрібний надійний ресурс, але офіційний звіт є масовим, пропоную прочитати наступне:

  1. Абсолютний мінімум кожен розробник програмного забезпечення абсолютно, позитивно повинен знати про набори Unicode та символів (без виправдань!) . Вступ Джоела Спольського, генерального директора Stack Exchange.
  2. До БМП і далі! Навчальний посібник Еріка Мюллера, технічного директора, віце-президента згодом, в Консорціумі Unicode. (спочатку 20 слайдів, і ви готові)

Коротке пояснення:

Комп'ютери читають байти, а люди читають символи, тому ми використовуємо стандарти кодування для відображення символів у байти. ASCII був першим широко використовуваним стандартом, але охоплює лише латинську мову (7 біт / символ може представляти 128 різних символів). Unicode - це стандарт, який має на меті охопити всі можливі символи у світі (може містити до 1,114,112 символів, тобто 21 біт / символ максимум. Поточний Unicode 8.0 задає загалом 120 737 символів, і це все).

Основна відмінність полягає в тому, що символ ASCII може підходити до байту (8 біт), але більшість символів Unicode не може. Таким чином, використовуються форми / схеми кодування (як UTF-8 і UTF-16), і модель символів має такий вигляд:

Кожен символ займає нумеровану позицію від 0 до 1,114,111 (hex: 0-10FFFF), що називається кодовою точкою . Кодирующая форма відображає точку коду в код блоку послідовності. Блок коду є спосіб , яким Ви хочете символи , які будуть організовані в пам'яті, 8-бітних, 16-бітових блоків і так далі. UTF-8 використовує від 1 до 4 одиниць з 8 біт, а UTF-16 використовує 1 або 2 одиниці з 16 біт, щоб покрити весь Unicode максимум 21 біт. Одиниці використовують префікси, щоб межі символів можна було помітити, а більше одиниць означає більше префіксів, які займають біти. Отже, хоча UTF-8 використовує 1 байт для латинського сценарію, йому потрібні 3 байти для пізніших сценаріїв у базовій багатомовній площині, тоді як UTF-16 використовує 2 байти для всіх цих. І в цьому їх головна відмінність. Нарешті, схема кодування

(наприклад, UTF-16BE або UTF-16LE) відображає (серіалізує) послідовність одиниць коду до послідовності байтів.

символ: π
код точки: U + 03C0
форми кодування (кодові одиниці):
      UTF-8: CF 80
      UTF-16: 03C0
схеми кодування (байти):
      UTF-8: CF 80
      UTF-16BE: 03 C0
      UTF-16LE: C0 03

Порада: шестнадцатеричная цифра представляє 4 біта, тому двозначне шістнадцяткове число представляє байт
Також дивіться на площину карти в Вікіпедії , щоб отримати почуття набору символів макета


19

Спочатку Unicode повинен був мати 16-бітове кодування фіксованої ширини (UCS-2). Ранні користувачі Unicode, такі як Java та Windows NT, створили свої бібліотеки навколо 16-бітних рядків.

Пізніше сферу дії Unicode було розширено, щоб включити історичні символи, для яких знадобиться більше 65,536 кодових точок, які підтримує 16-бітове кодування. Щоб дозволити представлення додаткових символів на платформах, які використовували UCS-2, було введено кодування UTF-16. Він використовує "сурогатні пари" для представлення символів у додаткових площинах.

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


3
Варто зазначити, що Microsoft все ще називає UTF-16 як Unicode, додаючи до плутанини. Два не однакові.
Марк Рансом

15

У цій статті пояснюються всі подробиці http://kunststube.net/encoding/

ПИСЬМО НА БУФЕР

якщо ви записуєте в 4-байтний буфер, символ із кодуванням UTF8, ваш двійковий файл буде виглядати приблизно так:

00000000 11100011 10000001 10000010

якщо ви записуєте в 4-байтний буфер, символ із кодуванням UTF16, ваш двійковий файл буде виглядати приблизно так:

00000000 00000000 00110000 01000010

Як бачите, залежно від того, якою мовою ви б користувалися у своєму вмісті, це відповідно вплине на вашу пам'ять.

Наприклад, для цього конкретного символу: кодування UTF16 є більш ефективною, оскільки для наступного символу у нас є 2 резервні байти. Але це не означає, що ви повинні використовувати UTF16 для японського алфавіту.

ЧИТАННЯ З БУФЕРА

Тепер, якщо ви хочете прочитати вищевказані байти, ви повинні знати, в яке кодування було написано, і правильно їх розшифрувати.

Наприклад, якщо ви розшифруєте це: 00000000 11100011 10000001 10000010 в кодування UTF16, ви отримаєте не

Примітка: Кодування та Unicode - це дві різні речі. Unicode - це велика (таблиця) з кожним символом, відображеним в унікальній кодовій точці. наприклад, символ (літера) має (кодова точка) : 30 42 (шістнадцятковий). З іншого боку, кодування - це алгоритм, який перетворює символи на більш підходящий спосіб при зберіганні до обладнання.

30 42 (hex) - > UTF8 encoding - > E3 81 82 (hex), which is above result in binary.

30 42 (hex) - > UTF16 encoding - > 30 42 (hex), which is above result in binary.

введіть тут опис зображення


11

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

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

Вибір конкретного кодування залежить від ваших вимог. Різні кодування мають різні вимоги до пам'яті, і залежно від символів, з якими ви матимете справу, вам слід вибрати кодування, яке використовує найменші послідовності байтів для кодування цих символів.

Щоб отримати докладніші відомості про Unicode, UTF-8 та UTF-16, ви можете ознайомитися з цією статтею,

Що повинен знати кожен програміст про Unicode


9

Чому Unicode? Тому що ASCII має всього 127 символів. Від 128 до 255 осіб відрізняються в різних країнах, тому існують кодові сторінки. Тому вони сказали, що в летах може бути до 1114111 символів. Тож як ви зберігаєте найвищу кодову точку? Вам потрібно буде зберігати його, використовуючи 21 біт, тож ви будете використовувати DWORD, маючи 32 біти з 11 бітами. Отже, якщо ви використовуєте DWORD для зберігання символу unicode, це найпростіший спосіб, оскільки значення у вашому DWORD відповідає точно кодовій точці. Але масиви DWORD, звичайно, більше, ніж масиви WORD, і, звичайно, навіть більше, ніж масиви BYTE. Ось чому існує не тільки utf-32, але і utf-16. Але utf-16 означає потік WORD, а WORD має 16 біт, то як найвища кодова точка 1114111 може вписатися у WORD? Це не може! Таким чином, вони ставлять усе, що вище 65535, у DWORD, яке вони називають сурогатною парою. Така сурогатна пара - це два слова, і їх можна виявити, переглянувши перші 6 біт. То як щодо utf-8? Це байтовий масив або потік байтів, але як найвища кодова точка 1114111 може вписатися в байт? Це не може! Гаразд, значить, вони також вводять DWORD так? Або можливо СЛОВ, так? Майже правильно! Вони винайшли послідовності utf-8, що означає, що кожна кодова точка, що перевищує 127, повинна бути закодована у 2-байтну, 3-байтну або 4-байтну послідовності. Оце Так! Але як ми можемо виявити такі послідовності? Ну, все до 127 - це ASCII і є єдиним байтом. Що починається з 110, це двобайтова послідовність, що починається з 1110, це трибайтова послідовність, а те, що починається з 11110, є чотирьохбайтовою послідовністю. Решта бітів цих так званих "стартбайтів" належать до кодової точки. Тепер, залежно від послідовності, повинні слідувати наступні байти. Наступний байт починається з 10, решта бітів - 6 біт корисного навантаження і належать до кодової точки. Об'єднайте біти корисного навантаження стартового байта та наступних байт / с, і ви отримаєте кодову точку. Ось і вся магія utf-8.


3
utf-8 приклад знака € (Євро), декодований у 3-байтовій послідовності utf-8: E2 = 11100010 82 = 10000010 AC = 10101100 Як ви бачите, E2 починається з 1110, тому це трибайтова послідовність. , 82, а також AC починається з 10, тому це наступні байти. Тепер ми об'єднуємо "біти корисного навантаження": 0010 + 000010 + 101100 = 10000010101100, що становить десятковий 8364, тому 8364 повинен бути кодовою точкою для знака € (євро).
яскравий

5

ASCII - Програмне забезпечення виділяє лише 8-ти бітний байт в пам'яті для заданого символу. Він добре працює для англійських та прийнятих (позичкових слів, як фасад) символів, оскільки їх відповідні десяткові значення падають нижче 128 у десятковому значенні. Приклад C програма.

UTF-8 - Програмне забезпечення виділяє від 1 до 4 змінних 8-бітових байтів для заданого символу. Що означає тут змінна? Скажімо, ви надсилаєте символ "A" через свої сторінки HTML у браузері (HTML - UTF-8), відповідне десяткове значення A - 65, при перетворенні його в десяткове воно стає 01000010. Для цього потрібно лише 1 байт , 1 байт пам’яті виділяється навіть для спеціальних прийнятих англійських символів, таких як 'ç' у слові façade. Однак, коли ви хочете зберігати європейські символи, для цього потрібно 2 байти, тому вам потрібен UTF-8. Однак, якщо ви переходите до азіатських символів, вам потрібно мінімум 2 байти і максимум 4 байти. Аналогічно, для Emoji потрібно 3–4 байти. UTF-8 вирішить всі ваші потреби.

UTF-16 виділить мінімум 2 байти і максимум 4 байти на символ, він не виділить 1 або 3 байти. Кожен символ представлений або в 16 бітах, або в 32 бітах.

Тоді чому існує UTF-16? Спочатку Unicode був 16-ти бітним, а не 8-бітним. Java прийняла оригінальну версію UTF-16.

Якщо коротко, то UTF-16 вам ніде не потрібен, якщо він вже не прийнятий мовою чи платформою, над якою ви працюєте.

Програма Java, на яку посилаються веб-браузери, використовує UTF-16, але веб-браузер надсилає символи за допомогою UTF-8.


"Вам не потрібен UTF-16 ніде, якщо він вже не прийнятий мовою чи платформою": Це хороший момент, але тут є невключений список: JavaScript, Java, .NET, SQL NCHAR, SQL NVARCHAR , VB4, VB5, VB6, VBA, VBScript, NTFS, Windows API….
Том Блоджет

2

UTF розшифровується як стенд для Unicode Transformation Format. В основному в сучасному світі є сценарії, написані сотнями інших мов, формати, не охоплені базовим ASCII, використовуваним раніше. Отже, UTF виник.

UTF-8 має можливості кодування символів, а його кодова одиниця становить 8 біт, а для UTF-16 - 16 біт.

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