Юнікод - це дуже великий і складний світ, адже стандарт дозволяє ні багато ні мало представляти і працювати в комп'ютері з усіма основними письменностями світу. Деякі системи письма існують вже понад тисячу років, причому багато хто з них розвивалися майже незалежно один від одного в різних куточках світу. Люди так багато всього придумали і воно часто настільки несхоже один на одного, що об'єднати все це в єдиний стандарт було вкрай непростий і амбітним завданням.
Щоб по-справжньому розібратися з Юникоде потрібно хоча б поверхово уявляти собі особливості всіх писемностей, з якими дозволяє працювати стандарт. Але чи так це потрібно кожному розробнику? Ми скажемо, що немає. Для використання Юнікоду в більшості повсякденних завдань, достатньо володіти розумним мінімумом відомостей, а далі заглиблюватися в стандарт в міру необхідності.
У статті ми розповімо про основні принципи Юникода і висвітлимо ті важливі практичні питання, з якими розробники неодмінно зіткнуться в своїй повсякденній роботі.
Навіщо знадобився Юнікод?
До появи Юникода, майже повсюдно використовувалися однобайтні кодування, в яких межа між самими символами, їх поданням до пам'яті комп'ютера і відображенням на екрані була досить умовною. Якщо ви працювали з тим чи іншим національним мовою, то у вашій системі були встановлені відповідні шрифти-кодування, які дозволяли малювати байти з диска на екрані таким чином, щоб вони представляли сенс для користувача.
Якщо ви розпечатували на принтері текстовий файл і на паперовій сторінці бачили набір незрозумілих кракозябри, це означало, що на принтер незавантажені відповідні шрифти і воно інтерпретує байти не так, як вам би цього хотілося.
У такого підходу в цілому і однобайтових кодувань зокрема був ряд істотних недоліків:
- Можна було одночасно працювати лише з 256 символами, причому перші 128 були зарезервовані під латинські і керуючі символи, а в другій половині крім символів національного алфавіту потрібно було знайти місце для символів псевдографіки (╔ ╗).
- Шрифти були прив'язані до конкретної кодуванні.
- Кожна кодування представляла свій набір символів і конвертація з однієї в іншу була можлива тільки з частковими втратами, коли відсутні символи замінювалися на графічно схожі.
- Перенесення файлів між пристроями під керуванням різних операційних систем був скрутний. Потрібно було або мати програму-конвертер, або тягати разом з файлом додаткові шрифти. Існування Інтернету яким ми його знаємо було неможливим.
- У світі існують неалфавітні системи письма (ієрогліфічне письмо), які в однобайтном кодуванні непредставіми в принципі.
Основні принципи Юникода
Всі ми прекрасно розуміємо, що комп'ютер ні про які ідеальних сутності знати не знає, а оперує битами і байтами. Але комп'ютерні системи поки створюють люди, а не машини, і для нас з вами іноді буває зручніше оперувати умоглядними концепціями, а потім вже переходити від абстрактного до конкретного.
Важливо! Одному з центральних принципів в філософії Юникода є чітке розмежування між символами, їх поданням до комп'ютері і їх відображенням на пристрої виведення.
Вводиться поняття абстрактного юнікод-символу, що існує виключно у вигляді умоглядної концепції і домовленості між людьми, закріпленої стандартом. Кожному юнікод-символу поставлено у відповідність невід'ємне ціле число, що називається його кодової позицією (code point).
Так, наприклад, юнікод-символ U + 041F - це заголовна кирилична буква П. Існує кілька можливостей подання даного символу в пам'яті комп'ютера, рівно як і кілька тисяч способів відображення його на екрані монітора. Але при цьому П, воно і в Африці буде П або U + 041F.
Це добре нам знайома інкапсуляція або відділення інтерфейсу від реалізації - концепція, що відмінно зарекомендувала себе в програмуванні.
Виходить, що керуючись стандартом, будь-який текст можна закодувати у вигляді послідовності юнікод-символів
записати на листочку, упакувати в конверт і переслати в будь-який кінець Землі. Якщо там знають про існування Юникода, то текст буде сприйнятий ними рівно так само, як і нами з вами. У них не буде жодних сумнівів, що передостанній символ - це саме кирилична рядкова е (U + 0435), а не скажімо латинська маленька e (U + 0065). Зверніть увагу, що ми ні слова не сказали про байтовому поданні.
Кодова простір Юникода
Кодова простір Юникода складається из 1 114 112 кодових позицій в діапазоні від 0 до 10FFFF. З них до дев'ятої версії стандарту значення присвоєно лише 128 237. Частина простору зарезервована для приватного використання і консорціум Юникода обіцяє ніколи не привласнювати значення позиціях з цих спеціальний областей.
Якщо ми хочемо переслати текст через Інтернет, то нам буде потрібно закодувати послідовність Юнікод-символів у вигляді послідовності байтів.
Стандарт Юникода включає в себе опис ряду юнікод-кодувань, наприклад UTF-8 і UTF-16BE / UTF-16LE, які дозволяють кодувати весь простір кодових позицій. Конвертація між цими кодуваннями може вільно здійснюватися без втрат інформації.
Також ніхто не відміняв однобайтні кодування, але вони дозволяють закодувати свій індивідуальний і дуже вузький шматочок юнікод-спектра - максимум 256 кодових позицій. Для таких кодувань існують і доступні всім бажаючим таблиці, де кожному значенню єдиного байта зіставлений юнікод-символ (див. Наприклад CP1251.TXT). Незважаючи на обмеження, однобайтні кодування виявляються досить практичними, якщо мова йде про роботу з великим масивом моноязиковой текстової інформації.
Зверніть увагу, що UTF-8 - це кодування зі змінною довжиною коду. Кожен юнікод-символ в ній представляється послідовністю кодових квантів з мінімальною довжиною в один квант. Число 8 означає бітову довжину кодового кванта (code unit) - 8 біт. Для сімейства кодувань UTF-16 розмір кодового кванта становить, відповідно, 16 біт. Для UTF-32 - 32 біта.
Для зберігання строкової інформації в додатках часто використовуються 16-бітові юнікод-кодування в силу їх простоти, а так само той факт, що символи основних світових систем письма кодуються одним шестнадцатібітовим квантом. Так, наприклад, Java для внутрішнього представлення рядків успішно застосовує UTF-16. Операційна система Windows всередині себе також використовує UTF-16.
У будь-якому випадку, поки ми залишаємося в просторі Юникода, не так вже й важливо, як зберігається строкова інформація в рамках окремого додатка. Якщо внутрішній формат зберігання дозволяє коректно кодувати все мільйон з гаком кодових позицій і на кордоні додатки, наприклад при читанні з файлу або копіюванні в буфер обміну, не відбувається втрат інформації, то все добре.
У сухому залишку
Інформації багато і має сенс навести коротку вижимки за все, що було написано вище:
- Юнікод постулює чітке розмежування між символами, їх поданням до комп'ютері і їх відображенням на пристрої виведення.
- Кодова простір Юникода складається из 1 114 112 кодових позицій в діапазоні від 0 до 10FFFF.
- Базова багатомовна площину включає в себе юнікод-символи від U + 0000 до U + FFFF, які кодуються в UTF-16 двома байтами.
- Будь-яка юнікод-кодування дозволяє закодувати весь простір кодових позицій Юникода і конвертація між різними такими кодуваннями здійснюється без втрат інформації.
- Однобайтні кодування дозволяють закодувати лише невелику частину юнікод-спектра, але можуть виявитися корисними при роботі з великим об'ємом моноязиковой інформації.
- Кодування UTF-8 і UTF-16 мають змінною довжиною коду. В UTF-8 кожен юнікод-символ може бути закодований одним, двома, трьома або чотирма байтами. В UTF-16 - двома або чотирма байтами.
- Внутрішній формат зберігання текстової інформації в рамках окремої програми може бути довільним за умови коректної роботи з усім простором кодових позицій Юникода і відсутності втрат під час транскордонного передачі даних.
Короткий зауваження про кодування
З терміном кодування може статися деяка плутанина. В рамках Юникода кодування відбувається двічі. Перший раз кодується набір символів Юнікоду (character set), в тому сенсі, що кожному юнікод-символу ставиться з відповідність кодова позиція. В рамках цього процесу набір символів Юнікоду перетворюється в кодований набір символів (coded character set). Другий раз послідовність Юнікод-символів перетворюється в рядок байтів і цей процес також називається кодування.
В англомовній термінології існують два різних дієслова to code і to encode, але навіть носії мови часто в них плутаються. До того ж термін набір символів (character set або charset) використовується як синонім до терміну кодований набір символів (coded character set).
Все це ми говоримо до того, що має сенс звертати увагу на контекст і розрізняти ситуації, коли мова йде про кодової позиції абстрактного юнікод-символу і коли мова йде про його байтовому поданні.