Скільки важить символ в кодуванні unicode. Кодування Unicode

Юнікод

Матеріал з Вікіпедії - вільної енциклопедії

Перейти до: навігація, пошук

Юнікод   (Найчастіше) або Унікод (англ. Unicode) - стандарт кодування символів, Що дозволяє представити знаки практично всіх письмових мов.

Стандарт запропонований в 1991 році  некомерційною організацією «Консорціум Юнікоду» ( англ. Unicode Consortium, Unicode Inc. ).   Застосування цього стандарту дозволяє закодувати дуже велике число символів з різних писемностей: у документах Unicode можуть сусідити китайські ієрогліфи, Математичні символи, букви грецького алфавіту, латиниці  і кирилиці, При цьому стає непотрібним переключення кодових сторінок.

Стандарт складається з двох основних розділів: універсальний набір символів ( англ. UCS, universal character set) І сімейство кодувань ( англ. UTF, Unicode transformation format). Універсальний набір символів задає однозначну відповідність символів кодами  - елементам кодового простору, що представляє невід'ємні цілі числа. Сімейство кодувань визначає машинне представлення послідовності кодів UCS.

Коди в стандарті Юнікод розділені на кілька областей. Область з кодами від U + 0000 до U + 007F містить символи набору ASCII  з відповідними кодами. Далі розташовані області знаків різних писемностей, знаки пунктуації та технічні символи. Частина кодів зарезервована для використання в майбутньому.   Під символи кирилиці виділені області знаків з кодами від U + 0400 до U + 052F, від U + 2DE0 до U + 2DFF, від U + A640 до U + A69F (див. Кирилиця в Юникоде).

    1 Передумови створення і розвиток Юникода

    2 Версії Юникода

    3 Кодова простір

    4 Система кодування

    5 Модифікуючі символи

    6 Форми нормалізації

    • 6.1 Приклади

    7 Двонаправлене лист

    8 Представлені символи

    9 ISO / IEC 10646

    10 Способи подання

    • 10.1 UTF-8

      10.2 Порядок байтів

      10.3 Юнікод і традиційні кодування

      10.4 Реалізації

    11 Методи введення

    • 11.1 Microsoft Windows

      11.2 Macintosh

      11.3 GNU / Linux

    12 Проблеми Юникода

    13 «Юнікод» або «Унікод»?

    14 Див. Також

Передумови створення і розвиток Юникода

До кінця 1980-х років стандартом стали 8-бітові символи, при цьому існувало безліч різних 8-бітних кодувань, і постійно з'являлися все нові. Це пояснювалося як постійним розширенням кола підтримуваних мов, так і прагненням створити систему кодування, частково сумісну з якої-небудь іншої (характерний приклад - поява альтернативної кодування  для російської мови, обумовлене експлуатацією західних програм, створених для кодування CP437). В результаті з'явилося кілька проблем:

    проблема « кракозябри»(Відображення документів в неправильному кодуванні):    її можна було вирішити або послідовним впровадженням методів вказівки використовуваного кодування, або впровадженням єдиної для всіх кодування.

    Проблема обмеженості набору символів:    її можна було вирішити або перемиканням шрифтів всередині документа, або впровадженням «широкої» кодування. Перемикання шрифтів здавна практикувалося в текстових процесорах, Причому часто використовувалися шрифти з нестандартною кодуванням, Т. Н. «Dingbat fonts» - в результаті при спробі перенести документ в іншу систему все нестандартні символи перетворювалися в кракозябри.

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

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

Було визнано за необхідне створення єдиної «широкої» кодування. Кодування зі змінною довжиною символу, широко використовуються в Східній Азії, були визнані занадто складними у використанні, тому було вирішено використовувати символи фіксованої ширини. Використання 32-бітних символів здавалося занадто марнотратним, тому було вирішено використовувати 16-бітові.

Таким чином, перша версія Юникода представляла собою кодування з фіксованим розміром символу в 16 біт, тобто загальне число кодів було 2 16 (65 536). Звідси походить практика позначення символів чотирма шестнадцатерічнимі цифрами (наприклад, U + 04F0). При цьому в Юникоде планувалося кодувати не всі існуючі символи, а тільки ті, які необхідні в повсякденному побуті. Рідко використовувані символи повинні були розміщуватися в «області користувальницьких символів» (private use area), яка спочатку займала коди U + D800 ... U + F8FF. Щоб використовувати Юнікод також і в якості проміжної ланки при перетворенні різних кодувань один в одного, в нього включили всі символи, представлені у всіх найбільш відомих кодуваннях.

Надалі, проте, було прийнято рішення кодувати всі символи і в зв'язку з цим значно розширити кодову область. Одночасно з цим, коди символів стали розглядатися не як 16-бітові значення, а як абстрактні числа, які в комп'ютері можуть представлятися безліччю різних способів  (Див. способи подання).

Оскільки в ряді комп'ютерних систем (наприклад, Windows NT ) Фіксовані 16-бітові символи вже використовувалися в якості кодування за замовчуванням, було вирішено все найбільш важливі знаки кодувати тільки в межах перших 65 536 позицій (так звана англ. basic multilingual plane, BMP). Інший простір використовується для «додаткових символів» ( англ. supplementary characters): Систем письма вимерлих мов або дуже рідко використовуваних китайських  ієрогліфів, математичних і музичних символів.

Для сумісності зі старими 16-бітними системами була винайдена система UTF-16, Де перші 65 536 позицій, за винятком позицій з інтервалу U + D800 ... U + DFFF, відображаються безпосередньо як 16-бітові числа, а решта представляються у вигляді «сурогатних пар» (перший елемент пари з області U + D800 ... U + DBFF , другий елемент пари з області U + DC00 ... U + DFFF). Для сурогатних пар була використана частина кодового простору (2048 позицій), раніше відведеного для «символів для приватного використання».

Оскільки в UTF-16 можна відобразити тільки 2 20 +2 16 -2048 (1 112 064) символів, то це число і було обрано в якості остаточної величини кодового простору Юнікоду.

Хоча кодова область Юникода була розширена за межі 2 16 вже у версії 2.0, перші символи в «верхній» області були розміщені тільки у версії 3.1.

Роль цієї кодування в веб-секторі постійно зростає, на початок 2010 року частка веб-сайтів, які використовують Юнікод, склала близько 50%.

версії Юникода

У міру зміни і поповнення таблиці символів системи Юникода і виходу нових версій цієї системи, - а ця робота ведеться постійно, оскільки спочатку система Юнікод включала тільки Plane 0 - двухбайтное коди, - виходять і нові документи ISO. Система Юнікод існує в цілому в наступних версіях:

    1.1 (відповідає стандарту ISO / IEC 10646-1: 1993 ), Стандарт 1991-1995 років.

    2.0, 2.1 (той же стандарт ISO / IEC 10646-1: 1993 плюс доповнення: «Amendments» з 1-го по 7-е і «Technical Corrigenda» 1 і 2), стандарт 1996 року.

    3.0 (стандарт ISO / IEC 10646-1: 2000), стандарт 2000 року.

    3.1 (стандарти ISO / IEC 10646-1: 2000 та ISO / IEC 10646-2: 2001), стандарт 2001 року.

    3.2, стандарт 2002 року.

    4.0, стандарт 2003 .

    4.01, стандарт 2004 .

    4.1, стандарт 2005 .

    5.0, стандарт 2006 .

    5.1, стандарт 2008 .

    5.2, стандарт 2009 .

    6.0, стандарт 2010 .

    6.1, стандарт 2012 .

    6.2, стандарт 2012 .

кодова простір

Хоча форми записи UTF-8 і UTF-32 дозволяють кодувати до 2 31 (2 147 483 648) кодових позицій, було прийнято рішення використовувати лише 1 112 064 для сумісності з UTF-16. Втім, навіть і цього на поточний момент більш ніж достатньо - у версії 6.0 використовується трохи менше 110 000 кодових позицій (109 242 графічних та 273 інших символів).

Кодова простір розбито на 17 площин  по 2 16 (65536) символів. Нульова площина називається базової, В ній розташовані символи найбільш уживаних писемностей. Перша площина використовується, в основному, для історичних писемностей, друга - для рідко використовуваних ієрогліфів ККЯ, Третя зарезервована для архаїчних китайських ієрогліфів   . Площині 15 і 16 виділені для приватного вживання.

Для позначення символів Unicode використовується запис виду «U + xxxx»(Для кодів 0 ... FFFF), або« U + xxxxx»(Для кодів 10000 ... FFFFF), або« U + xxxxxx»(Для кодів 100000 ... 10FFFF), де xxx - шістнадцятиричні  цифри. Наприклад, символ «я» (U + 044F) має код 044F 16 = 1103 10 .

система кодування

Універсальна система кодування (Юнікод) являє собою набір графічних символів і спосіб їх кодування для комп'ютерної  обробки текстових даних.

Графічні символи - це символи, які мають видиме зображення. Графічним символам протиставляються керуючі символи і символи форматування.

Графічні символи включають в себе наступні групи:

  • знаки пунктуації;

    спеціальні знаки ( математичні, Технічні, ідеограми   та ін.);

    роздільники.

Юнікод - це система для лінійного представлення тексту. Символи, що мають додаткові над- або підрядкові елементи, можуть бути представлені у вигляді побудованої за певними правилами послідовності кодів (складовою варіант, composite character) або у вигляді єдиного символу (монолітний варіант, precomposed character).

модифікуючі символи

Представлення символу «Ї» (U + 0419) у вигляді базового символу «І» (U + 0418) і модифікує символу «̆» (U + 0306)

Графічні символи в Юникоде підрозділяються на протяжні і непротяжних (бесшірінние). Непротяжних символи при відображенні не займають місця в рядку. До них відносяться, зокрема, знаки наголосу і інші діакритичні знаки. Як протяжні, так і непротяжних символи мають власні коди. Протяжні символи інакше називаються базовими ( англ. base characters), А непротяжних - модифікують ( англ. combining characters); причому останні не можуть зустрічатися самостійно. Наприклад, символ «á» може бути представлений як послідовність базового символу «a» (U + 0061) і модифікує символу «» (U + 0301) або як монолітний символ «á» (U + 00C1).

Особливий тип модифікують символів - селектори варіантів накреслення ( англ. variation selectors). Вони діють тільки на ті символи, для яких такі варіанти визначені. У версії 5.0 варіанти накреслення визначені для ряду математичних символів, для символів традиційного монгольського алфавіту  і для символів монгольського квадратного листа.

форми нормалізації

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

У стандарті Юнікод визначені 4 форми нормалізації тексту:

    Форма нормалізації D (NFD) - канонічна декомпозиція. В процесі приведення тексту в цю форму всі складові символи рекурсивно замінюються на кілька складових, відповідно до таблиць декомпозиції.

    Форма нормалізації C (NFC) - канонічна декомпозиція з подальшою канонічної композицією. Спочатку текст наводиться до форми D, після чого виконується канонічна композиція - текст обробляється від початку до кінця і виконуються наступні правила:

    • Символ S є початковим, Якщо він має нульовий клас модифікації в базі символів Юнікоду.

      У будь-якій послідовності символів, що стартує з початкового символу S, символ C блокується від S, якщо і тільки якщо між S і C є якийсь символ B, який або є початковим, або має однаковий або більший клас модифікації, ніж C. Це правило поширюється тільки на рядки, які пройшли канонічну декомпозицію.

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

      Символ X може бути первинно суміщений з символом Y, якщо і тільки якщо існує первинний композит Z, канонічно еквівалентний послідовності .

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

    Форма нормалізації KD (NFKD) - сумісна декомпозиція. При приведенні в цю форму всі складові символи замінюються, використовуючи як канонічні карти декомпозиції Юникода, так і сумісні карти декомпозиції, після чого результат ставиться в канонічному порядку.

    Форма нормалізації KC (NFKC) - сумісна декомпозиція з подальшою канонічної   композицією.

Терміни «композиція» та «декомпозиція» розуміють під собою відповідно з'єднання або розкладання символів на складові частини.

приклади

Початковий текст

\\ U0410, \\ u0401, \\ u0419

\\ U0410, \\ u0415 \\ u0308 \\ u0418 \\ u0306

\\ U0410, \\ u0401, \\ u0419

двонаправлене лист

Стандарт Юнікод підтримує писемності мов як з напрямком написання зліва направо ( англ. left- to- right, LTR), Так і з написанням справа наліво ( англ. right- to- left, RTL) - наприклад, арабське  і єврейське  лист. В обох випадках символи зберігаються в «природному» порядку; їх відображення з урахуванням потрібного напрямку письма забезпечується додатком.

Крім того, Юнікод підтримує комбіновані тексти, що поєднують фрагменти з різним напрямком письма. Дана можливість називається двунаправленность (англ. bidirectional text, BiDi). Деякі спрощені обробники тексту (наприклад, в стільникових телефонах) Можуть підтримувати Юнікод, але не мати підтримки двобічної. Всі символи Юнікоду поділені на кілька категорій: пишуться зліва направо, що пишуться справа наліво, і пишуться в будь-якому напрямку. Символи останньої категорії (в основному це знаки пунктуації) При відображенні приймають напрямок навколишнього їх тексту.

презентовані символи

Основна стаття: Символи, представлені в Юникоде

Схема базової площини Unicode, см. опис

Юнікод включає практично всі сучасні писемності, в тому числі:

    арабську,

    вірменську,

    бенгальську,

    бірманську,

    глаголицю,

    грецьку,

    грузинську,

    деванагари,

    єврейську,

    кирилицю,

    китайську   (Китайські ієрогліфи активно використовуються в японській мові, А також досить рідко в корейському),

    коптську,

    кхмерскую,

    латинську,

    тамільських,

    корейську (хангиль),

    черокі,

    ефіопську,

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

та інші.

З академічними цілями додані багато історичних писемності, в тому числі: німецькі руни, древнетюркские руни, давньогрецька, єгипетські ієрогліфи, клинопис, писемність майя, етруська алфавіт.

У Юникоде представлений широкий набір математичних  і музичних  символів, а також піктограм.

Однак в Юнікод принципово не включаються логотипи компаній і продуктів, хоча вони і зустрічаються в шрифтах (наприклад, логотип Apple  в кодуванні MacRoman  (0xF0) або логотип Windows  в шрифті Wingdings (0xFF)). У юнікодовскіх шрифтах логотипи повинні розміщуватися тільки в області користувальницьких символів.

ISO / IEC 10646

Консорціум Юнікоду працює в тісному зв'язку з робочою групою ISO / IEC / JTC1 / SC2 / WG2, яка займається розробкою міжнародного стандарту 10646 ( ISO/IEC  10646). Між стандартом Юникода і ISO / IEC 10646 встановлена ​​синхронізація, хоча кожен стандарт використовує свою термінологію і систему документації.

Співпраця Консорціуму Юникода з Міжнародною організацією зі стандартизації ( англ. International Organization for Standardization, ISO) Почалося в 1991 році. В 1993 році  ISO випустила стандарт DIS 10646.1. Для синхронізації з ним Консорціум затвердив стандарт Юнікод версії 1.1, в який були внесені додаткові символи з DIS 10646.1. В результаті значення закодованих символів в Unicode 1.1 і DIS 10646.1 повністю збіглися.

Надалі співпраця двох організацій продовжилося. В 2000 році  стандарт Unicode 3.0 був синхронізований з ISO / IEC 10646-1: 2000. Майбутня третя версія ISO / IEC 10646 буде синхронізована з Unicode 4.0. Можливо, ці специфікації навіть будуть опубліковані як єдиний стандарт.

Аналогічно форматам UTF-16 і UTF-32 в стандарті Юнікод, стандарт ISO / IEC 10646 також має дві основні форми кодування символів: UCS-2 (2 байта на символ, аналогічно UTF-16) і UCS-4 (4 байта на символ, аналогічно UTF-32). UCS значить універсальний многооктетний (Мультибайтних) кодований набір символів (англ. universal multiple- octet coded character set). UCS-2 можна вважати підмножиною UTF-16 (UTF-16 без сурогатних пар), а UCS-4 є синонімом для UTF-32.

способи подання

Юнікод має кілька форм представлення ( англ. Unicode transformation format, UTF): UTF-8, UTF-16  (UTF-16BE, UTF-16LE) і UTF-32 (UTF-32BE, UTF-32LE). Була розроблена також форма подання UTF-7 для передачі по семібітним каналах, але через несумісність з ASCII  вона не набула поширення і не включена в стандарт. 1 квітня 2005 року  було запропоновано дві жартівливі форми подання: UTF-9 і UTF-18 ( RFC 4042).

В Microsoft Windows NT  і заснованих на ній системах Windows 2000  і Windows XP  переважно використовується  форма UTF-16LE. В UNIX-подібних операційних системах GNU / Linux, BSD  і Mac OS X  прийнята форма UTF-8 для файлів і UTF-32 або UTF-8 для обробки символів в оперативної пам'яті.

Punycode  - інша форма кодування послідовностей Unicode-символів в так звані ACE-послідовності, які складаються тільки з алфавітно-цифрових символів, як це дозволено в доменних іменах.

Основна стаття: UTF-8

UTF-8 - уявлення Юникода, що забезпечує найкращу сумісність зі старими системами, які використовували 8-бітові символи. Текст, що складається тільки з символів з номером менше 128, при записі в UTF-8 перетворюється в звичайний текст ASCII. І навпаки, в тексті UTF-8 будь байт  зі значенням менше 128 зображує символ ASCII з тим же кодом. Решта символів Юнікоду зображуються послідовностями довжиною від 2 до 6 байт (на ділі, тільки до 4 байт, оскільки в Юникоде немає символів з кодом більше 10FFFF, і вводити їх в майбутньому не планується), в яких перший байт завжди має вид 11xxxxxx, а решта - 10xxxxxx.

Формат UTF-8 був винайдений 2 вересня 1992 року Кеном Томпсоном  і Робом Пайком  і реалізований в Plan 9   . Зараз стандарт UTF-8 офіційно закріплений в документах RFC 3629  і ISO / IEC 10646 Annex D.

Символи UTF-8 виходять з Unicode наступним чином:

0x00000000 - 0x0000007F: 0xxxxxxx

0x00000080 - 0x000007FF: 110xxxxx 10xxxxxx

0x00000800 - 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx

0x00010000 - 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Теоретично можливі, але не включені в стандарт також:

0x00200000 - 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

0x04000000 - 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

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

порядок байтів

У потоці даних UTF-16 старший байт може записуватися або перед молодшим ( англ. UTF-16 little-endian), Або після молодшого ( англ. UTF-16 big-endian). Аналогічно існує два варіанти четирёхбайтной кодування - UTF-32LE і UTF-32BE.

Для визначення формату представлення Юнікоду в початок текстового файлу записується сигнатура  - символ U + FEFF ( нерозривний пробіл  нульової довжини), також іменований міткою порядку байтів (англ. byte order mark, BOM ). Це дозволяє розрізняти UTF-16LE і UTF-16BE, оскільки символу U + FFFE не існує. Також цей спосіб іноді застосовується для позначення формату UTF-8, хоча до цього формату і не застосовується поняття порядку байтів. Файли, такі цією угодою, починаються з таких послідовностей байтів:

На жаль, цей спосіб не дозволяє надійно розрізняти UTF-16LE і UTF-32LE, оскільки символ U + 0000 допускається Юнікод (хоча реальні тексти рідко починаються з нього).

Файли в кодуваннях UTF-16 і UTF-32, що не містять BOM, повинні мати порядок байтів big-endian ( unicode.org).

Юнікод і традиційні кодування

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

Крім того, багато форматів даних дозволяють вставляти будь-які символи Юнікоду, навіть якщо документ записаний в старій 8-бітної кодуванні. Наприклад, в HTML можна використовувати коди з амперсандом.

реалізації

Більшість сучасних операційних систем в тій чи іншій мірі забезпечують підтримку Юнікоду.

В операційних системах сімейства Windows NT  для внутрішнього представлення імен файлів і інших системних рядків використовується двухбайтовая кодування UTF-16LE. Системні виклики, які беруть строкові параметри, існують в однобайтном і двухбайтное варіантах. Детальніше див. У статті .

UNIX-подібні операційні системи, в тому числі GNU / Linux, BSD, Mac OS X, Використовують для подання Юникода кодування UTF-8. Більшість програм можуть працювати з UTF-8 як з традиційними однобайтном кодуваннями, не звертаючи уваги на те, що символ представляється як кілька послідовних байт. Для роботи з окремими символами рядка зазвичай перекодуються в UCS-4, так що кожному символу відповідає машинне слово.

Однією з перших успішних комерційних реалізацій Юникода стала середовище програмування Java. У ній принципово відмовилися від 8-бітного представлення символів на користь 16-бітного. Це рішення збільшувало витрату пам'яті, але дозволило повернути в програмування важливу абстракцію: довільний одиночний символ (тип char). Зокрема, програміст міг працювати з рядком, як з простим масивом. На жаль, успіх не був остаточним, Юнікод переріс обмеження в 16 біт і до використання J2SE 5.0 довільний символ знову став займати змінне число одиниць пам'яті - один char або два (див. сурогатна пара).

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

методи введення

Оскільки жодна розкладка клавіатури  не може дозволити вводити всі символи Юнікоду одночасно, від операційних систем  і прикладних програм  потрібна підтримка альтернативних методів введення довільних символів Юнікоду.

Microsoft Windows

Основна стаття: Юнікод в операційних системах Microsoft

Починаючи з Windows 2000, Службова програма «Таблиця символів» (charmap.exe) показує всі символи в ОС і дозволяє копіювати їх в буфер обміну. Схожа таблиця є, наприклад, в Microsoft Word.

Іноді можна набрати шістнадцятковий  код, натиснути Alt+ X, і код буде замінений на відповідний символ, наприклад, в WordPad, Microsoft Word. У редакторах Alt + X виконує і зворотне перетворення.

У багатьох програмах MS Windows, щоб отримати символ Unicode, потрібно, утримуючи клавішу Alt набрати десяткове значення коду символу на цифровій клавіатурі. Наприклад, корисними при наборі кириличних текстів будуть комбінації Alt + 0171 ( «) і Alt + 0187 ("). Цікаві також комбінації Alt + 0133 (...) і Alt + 0151 (-).

Macintosh

В Mac OS 8.5 і пізніших версіях підтримується метод введення, званий «Unicode Hex Input». При затиснутою клавіші Option потрібно набрати чотиризначний шістнадцятковий код потрібного символу. Цей метод дозволяє вводити символи з кодами, великими U + FFFF, використовуючи пари сурогатів; такі пари операційною системою будуть автоматично замінені на поодинокі символи. Цей метод введення перед використанням потрібно активізувати в відповідному розділі системних налаштувань і потім вибрати як поточний метод введення в меню клавіатури.

Починаючи з Mac OS X  10.2, існує також додаток «Character Palette», що дозволяє вибирати символи з таблиці, в якій можна виділяти символи певного блоку або символи, які підтримуються конкретним шрифтом.

GNU / Linux

В GNOME  також є утиліта «Таблиця символів», що дозволяє відображати символи певного блоку або системи письма і надає можливість пошуку за назвою або опису символу. Коли код потрібного символу відомий, його можна ввести відповідно до стандарту ISO  14755: при затиснутих клавішах Ctrl + ⇧ Shift  ввести шістнадцятковий код (починаючи з деякої версії GTK + введення коду потрібно випередити натисканням клавіші «U»). Введений шістнадцятковий код може мати до 32 біт в довжину, дозволяючи вводити будь-які символи Юнікоду без використання сурогатних пар.

Unicode: UTF-8, UTF-16, UTF-32.

Юнікод являє собою набір графічних символів і спосіб їх кодування для комп'ютерної обробки текстових даних.

Юнікод не тільки приписує кожному символу унікальний код, але і визначає різні характеристики цього символу, наприклад:

    тип символу (прописна буква, мала літера, цифра, розділовий знак і т. д.);

    атрибути символу (відображення зліва направо або справа наліво, пробіл, розрив рядка і т. д.);

    відповідна прописна або рядкова буква (для малих і великих літер відповідно);

    відповідне числове значення (для цифрових символів).

    стандарти UTF  (Абревіатура Unicode Transformation Format) для представлення символів:

UTF-16: У Windows Vista для подання всіх Unicode- символів використовується кодування UTF-16. В UTF-16 символи представлені двома байтами (16 бітами). Ця кодування використовується в Windows, оскільки 16-бітними значеннями можна уявити символи, складові алфавіти більшості мов світу, це дозволяє програмам швидше обробляти рядки і обчислювати їх довжину. Однак для представлення символів алфавіту деяких мов 16 біт недостатньо. Для таких випадків UTE-16 підтримує «сурогатні» кодування, що дозволяють кодувати символи 32 бітами (4 байтами). Втім, додатків, яким доводиться мати справу з символами таких мов, мало, тому UTF-16 - хороший компроміс між економією пам'яті і простотою програмування. Зауважте, що в.NET Framework все символи кодуються з використанням UTF-16, тому застосування UTF-16 в Windows- додатках  підвищує продуктивність і знижує споживання пам'яті при передачі рядків між «рідним» і керованим кодом.

UTF-8: У кодуванні UTF-8 різні символи можуть бути представлені 1,2,3 або 4 байтами. Символи з значеннями менше 0x0080 стискаються до 1 байта, що дуже зручно для символів, що застосовуються в США. Символи, яким відповідають значення з діапазону 0x0080-0x07FF, перетворюються в 2-байтові значення, що добре працює з алфавітами європейських і близькосхідних мов. Символи з великими значеннями перетворюються в 3-байтові значення, зручні при роботі із середньоазіатськими мовами. Нарешті, «сурогатні» пари записуються в 4-байтовому форматі. UTF-8 надзвичайно популярна кодування. Однак її ефективність менше в порівнянні з UTF-16, якщо часто використовуються символи з значеннями 0x0800 і вище.

UTF-32: У UTF-32 все символи представлені 4 байтами. Це кодування зручна для написання простих алгоритмів для перебору символів будь-якої мови, які не потребують обробки символів, представлених різними числом байтів. Наприклад, при використанні UTF-32 можна забути про «сурогату», оскільки будь-який символ в цьому кодуванні представлений 4 байтами. Ясно, що з точки зору використання пам'яті ефективність UTF-32 далека від ідеалу. Тому дану кодування рідко застосовують для передачі рядків по мережі і збереження їх у файли. Як правило, UTF-32 використовується як внутрішній формат представлення даних в програмі.

UTF-8

Найближчим часом все більш важливу роль буде грати особливий формат Unicode (і ISO 10646) під назвою UTF-8. Ця «похідна» кодування користується для запису символів ланцюжками байтів різної довжини (від одного до шести), які за допомогою нескладного алгоритму перетворюються в Unicode- коди, причому більш вживаним символам відповідають більш короткі ланцюжки. Головне достоїнство цього формату - сумісність з ASCII не тільки за значеннями кодів, а й за кількістю біт на символ, так як для кодування будь-якого з перших 128 символів в UTF-8 досить одного байта (хоча, наприклад, для букв кирилиці потрібно вже по два байта).

Формат UTF-8 був винайдений 2 вересня 1992 року Кеном Томпсоном і Робом Пайком і реалізований в Plan 9. Зараз стандарт UTF-8 офіційно закріплений в документах RFC 3629 і ISO / IEC 10646 Annex D.

Для Web- дизайнера це кодування має особливе значення, так як саме вона оголошена «стандартної кодуванням документа» в HTML починаючи з версії 4.

Текст, що складається тільки з символів з номером менше 128, при записі в UTF-8 перетворюється в звичайний текст ASCII. І навпаки, в тексті UTF-8 будь-який байт із значенням менше 128 зображує символ ASCII з тим же кодом. Решта символів Юнікоду зображуються послідовностями довжиною від 2 до 6 байтів (реально тільки до 4 байт, оскільки використання кодів більше 221 не планується), в яких перший байт завжди має вид 11xxxxxx, а решта - 10xxxxxx.

Простіше кажучи, в форматі UTF-8 символи латинського алфавіту, розділові знаки і символи, що управляють ASCII записуються кодами US- ASCII, a всі інші символи кодуються за допомогою декількох октетів зі старшим бітом 1. Це призводить до двох ефектів.

    Навіть якщо програма НЕ розпізнає Юнікод, то латинські букви, арабські цифри  і розділові знаки будуть відображатися правильно.

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

    На перший погляд може здатися, що UTF-16 зручніше, так як в ній більшість символів кодується рівно двома байтами. Однак це зводиться нанівець необхідністю підтримки сурогатних пар, про які часто забувають при використанні UTF-16, реалізовуючи лише підтримку символів UCS-2.

  → Що таке Юнікод?

Що таке Юнікод?

Юнікод (Unicode), це багатомовний, заснований на ASCII стандарт кодування символів, а також, пов'язане з ним, сімейство багатобайтові кодувань. Якщо деякі слова у попередньому реченні вам не зрозумілі, давайте розглянемо їх докладніше.

Що таке кодування

Сучасні комп'ютери все ще досить дурні і, в більшості своїй, не вміють працювати ні з чим, окрім чисел. Ми розглядаємо на своїх моніторах фотографії, дивимося фільми, граємо в ігри. Але для комп'ютерів все це лише безликий потік нулів і одиничок. Так само і текст - для комп'ютера це просто набір байтів. Букви і будь-які інші символи представляються в машинному пам'яті, як числа.

Тому програмістам при роботі з текстом доводиться робити подібні угоди: «А давайте кожному символу буде відповідати один байт. Причому, якщо в байті буде число 43, то будемо вважати, що це цифра нуль. А якщо число 66, то нехай це буде заголовна латинська літера  B ».

Подібний список всіх використовуваних символів і відповідних їм чисел і називається кодуванням. Ви, швидше за все, вже чули назви багатьох кодувань: Windows-1251, KOI-8, ну і, звичайно, Unicode.

крякозябри

Напевно, часто бувала ситуація, коли ви відкриваєте сторінку в браузері, а там замість тексту якась мішанина з чудесних символів. Або просто суцільні знаки питання. Або ви пишете любовне лист своїй дівчині, а вона дзвонить вам і говорить «що за нечитаний марення ти мені прислав? Я образилася".

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

Наприклад, ваш текстовий редактор налаштований на кодування Windows-1251. І ви пишете «Здрастуйте, дорога Маша!». Ви натискаєте першу букву і програма думає: «ага, російська заголовна буква Зе - код 199". І записує число 199 в файл. Маша отримує ваш лист, але в її поштовому клієнті  стоїть кодування KOI8-R (тому що Маша любить старий Unix). А в цьому кодуванні числа 199 відповідає мала літера «г». І Маша читає: «гДПЮБЯРБСІРЕ, ДНПНЦЮ' лЮЬЮ!». Маша образилася!

Щоб подібного не відбувалося, потрібно якимось чином вказувати кодування в якому набраний текст. Наприклад, в HTML це робиться за допомогою тега:

ASCII

Практично всі сучасні кодування, що використовуються на персональних комп'ютерах є ASCII-сумісними. Тобто перші 128 символів у них кодуються однаково, а відмінності починаються з коду 128 і вище. Вищезазначені Windows-1251 і KOI8-r також засновані на ASCII і якби лист починалося б з «Hello, my dear Maria!», То непорозуміння не виникло б.

Заснований на ASCII і Юнікод.

однобайтні кодування

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

Однобайтні кодування всім гарні: вони компактні, з ними легко працювати (потрібно дістати п'ятий символ - просто беремо п'ятий байт від початку). Єдина проблема: в них міститься мало символів. Рівно стільки, скільки значень може приймати один байт, тобто зазвичай, це 256. Наприклад, в Windows-1251 ми віддали 128 символів під ASCII, додали 66 букв російського алфавіту (рядкові і заголовні), кілька знаків пунктуації та ось у нас вже залишається не так багато вільних позицій. Навіть на псевдографіку не вистачає.

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

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

багатобайтові кодування

Найпростішим рішенням було взяти два байта замість одного. Плюс такого рішення: тепер можна в рамках одного кодування використовувати 65 тисяч символів. Мінуси теж є:

  • Для всіх можливих символів, ієрогліфів і смайликів навіть 65 тисяч символів мало.
  • Текстові файли стали займати вдвічі більше місця, навіть тексти англійською. Занадто марнотратно.
  • Кодування перестали бути ASCII-сумісними і багато програм не могли з ними працювати.

стандарт Unicode

В кінцевому підсумку все вилилося в стандарт Юнікод, який так-сяк, але вирішує практично всі, хто стояв перед кодуваннями проблеми.

З одного боку, Юнікод дозволяє кодувати практично необмежену кількість символів. В останньому стандарті визначено більше 100 000 різних символів всіх сучасних і багатьох уже мертвих мов, а також різні іконки і піктограми. З іншого боку, деякі способи кодування дозволяють Юнікод залишатися ASCII-сумісними. Що дозволяє працювати, як і раніше багатьом програмам, а також американським і іншим англомовним користувачам, багато з яких появи Юникода навіть не помітили. У Юникоде також зібрані всі символи з усіх популярних стандартів кодування, що дозволяє перетворити в нього будь-який текст зі старої кодування.

Практично все сучасні програми, Що працюють з текстом, розуміють Юнікод. Більш того, зазвичай вони в ньому і працюють. Наприклад, навіть коли ви відкриваєте сайт в старій добрій Windows-1251, браузер спочатку всередині у себе перекодовує всі тексти в Юнікод, а потім відображає їх. Загалом, Юнікод, це світле майбутнє інтернету і всієї комп'ютерної індустрії.

Відмінність набору символів від кодування

Терміни «кодування», «стандарт кодування», «набір символів» зазвичай використовуються, як синоніми, але між ними є і тонкі відмінності. Важливо розуміти різницю між «стандартом» і, власне, «кодуванням». Якийсь стандарт просто говорить, що буква «A», це число 65, а буква «B» - 66. Кодування же відповідає за те, як ці числа уявити в пам'яті комп'ютера.

В епоху однобайтовим кодувань, ця різниця була практично невловимо. Число 65 - байт із значенням 65 або послідовність бітів 01000001. Для багатобайтові ж уже виникають питання: скільки байтів використовувати, в якому порядку, фіксоване число байтів чи ні?

Тобто в стандарті Юнікод визначено, що кириличної букви «А» відповідає абстрактне число 1040. Як уявити це число у вигляді послідовності байтів вирішує вже конкретна кодування - UTF-8, UTF-16, UTF-32.

Тобто текстовий файл не може бути в кодуванні «Юнікод», а тільки в конкретній кодуванні «UTF-8» або «UTF-16».

Кодування і шрифти

Юнікод, як і будь-яка інша кодування не описує того, як слід малювати символи. Для нього число 1040, це «кирилична заголовна буква А». А яка вона, друкована, прописна, похила, жирна або з завитками, це не його справа.

За зображення символу відповідають шрифти. Тому один і той же символ в різних шрифтах може виглядати по різному, а то і взагалі бути відсутнім.

Унікод або Юнікод (від англ. Слова Unicode) Є стандартом кодування знаків-символів. Він дає можливість бути представленими в кодуванні майже всім письмовим мов.

В кінці 1980-х роль стандарту закріпилася за 8-бітними символами. 8-бітові кодування були представлені різними модифікаціями, число яких постійно зростала. Головним чином, це було результатом активного розширення спектра використовуваних мов. Мало місце і прагнення розробників придумати кодування, яка претендує хоча б на часткову універсальність.

В результаті виникла необхідність займатися вирішенням декількох проблем:

  • проблеми індикації документів в некоректній кодуванні. Вирішити її було можна, або послідовно впроваджуючи методи вказівки застосовуваної кодування, або вводячи єдине кодування для всіх;
  • проблеми обмеженості пакета символів, що вирішується або шляхом перемикання шрифтів у документі, або впроваджуючи розширену кодування;
  • проблеми трансформування кодування з однієї в іншу, яку неможливо вирішити або використовуючи проміжне перетворення (третя кодування), що включає символи різних кодувань, або складаючи таблиці перекодування для кожних двох кодувань;
  • проблеми дублювання окремих шрифтів. Традиційно кожна кодування передбачала наявність свого шрифту, навіть коли кодування повністю або частково збігалися в наборі символів. В якійсь мірі проблема вирішувалася за допомогою «великих» шрифтів, з яких потім вибиралися символи, потрібні для конкретної кодування. Але для того, щоб визначити ступінь відповідності, потрібно створити єдиний реєстр символів.

Таким чином, на порядку денному постало питання про необхідність створення «широкої» єдиної кодування. Використовувані в Південно-східній Азії кодування із змінною довжиною символу виглядали надто складними в застосуванні. Тому упор був зроблений на використання символу, що має фіксовану ширину. 32-бітові символи здавалися надто громіздкими і перемогу в підсумку здобули 16-бітові.

Стандарт в 1991 році запропонувала інтернет-спільноті некомерційна організація «Консорціум Юнікоду». Його використання дає можливість закодувати велика кількість символів різних видів  писемності. В Unicode-документах не тісно в щільному сусідстві ні китайським ієрогліфів, ні математичним символам, ні кирилиці, ні латиниці. При цьому кодові сторінки  в процесі роботи не вимагають ніяких перемикань.

Складається стандарт з двох головних розділів: універсального набору символів (англ. UCS) і сімейства кодувань (в англійській інтерпретації - UTF). Універсальним набором символів задається однозначна пропорційність кодами символів. Коди в цьому випадку є елементи кодової сфери, які є невід'ємними цілими числами. Функція сімейства кодувань - визначення машинного уявлення послідовності UCS-кодів.

У Юнікод-стандарті коди градіровать по кількох областях. Ареал з кодами, починаючи з U + 0000 і закінчуючи U + 007F, - включає символи комплекту ASCII з необхідними кодами. Далі знаходяться області символів різних писемностей, символів технічних, знаків пунктуації. Окрему партію кодів зберігають в резерві для майбутнього застосування. Під кирилицю визначені наступні області символів з кодами: U + 0400 - U + 052F, U + 2DE0 - U + 2DFF, U + A640 - U + A69F.

Значення даного кодування в веб-просторі невблаганно зростає. Частка сайтів, які використовують Юнікод, становила на початку 2010 року майже 50 відсотків.

Java: Статті

Кодові точки Unicode і російські символи в початкових кодах і програмах Java. JDK 1.6.

  Досить багато розробників програмного забезпечення  в дійсності не мають до кінця чіткого уявлення про наборах символів, кодувань, Unicode і супутніх матеріалах. Навіть в даний час багатьма програмами часто ігноруються зустрічаються перетворення символів, навіть програмами, які, здавалося б, розроблені за допомогою дружніх до Unicode Java технологіях. Найчастіше безтурботно використовується для символів 8 бітів, що унеможливлює розробку хороших багатомовних web-додатків. Дана стаття є об'єднанням рядів статей з питань кодування Unicode, проте основною стала перероблена стаття Джоела Сполскі The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (08.10.2003).

Історія створення різних видів кодувань

Весь той матеріал, який говорить про те, що "простий текст = ASCII = символи з 8 біт", є не коректним. Єдиними символами, які могли відображатися коректно при будь-яких обставинах, це були англійські букви без діакритичних знаків з кодами від 32 до 127. Для цих символів існує код, названий ASCII, який був в стані уявити все символи. Буква "A" мала б код 65, прогалиною був би код 32, і т.п. Цим символом могли бути зручно збережені в 7 бітах. Більшість комп'ютерів в ті дні використовувало 8-бітові регістри, і таким чином ви не тільки могли зберігати будь-який можливий символ ASCII, Але ще і мали цілий біт економії, який, якщо у вас була така забаганка, ви могли використовувати в ваших власних цілях. Коди менше 32 називалися нецензурними і використовувалися для керуючих символів, наприклад, символ 7 змушував ваш комп'ютер видати сигнал динаміка, а символ 12 був символом кінця сторінки, змушуючи принтер прокрутити поточний аркуш паперу і завантажити новий.

Оскільки байти мають вісім бітів, то багато хто думав: "ми можемо використовувати коди 128-255 в наших власних цілях". Неприємність була в тому, що для дуже багатьох ця ідея прийшла майже одночасно, але у всіх були свої власні ідеї щодо того, що повинна розміщуватись на місці з кодами від 128 до 255. У IBM-PC було щось, що стало відомим як набір символів OEM, в якому було трохи діакритичних символів для європейських мов і набір символів для малювання ліній: горизонтальні смужки, вертикальні смужки, куточки, хрестики, і т.д. І ви могли використовувати ці символи для того, щоб робити елегантні кнопки і малювати лінії на екрані, які ви все ще можете побачити на деяких старих комп'ютерах. Наприклад, на деяких PC символ з кодом 130 показувався як e, але на комп'ютерах, проданих в Ізраїлі, це була єврейська буква Gimel (?). Якби американці посилали свої resume (резюме) в Ізраїль, вони прибували б як r? Sum ?. У багатьох випадках, як, наприклад, в разі російської мови, було багато різних ідей щодо того, що робити з верхніми 128 символами, і тому ви не могли навіть надійно обмінюватися російськомовними документами.

В кінцевому рахунку, різноманітність кодувань OEM було зведено в стандарт ANSI. Стандарт ANSI, обумовлював, які символи розташовувалися нижче 128, ця область в основному залишалася тією ж, що і в ASCII, але було багато різних способів звертатися з символами від 128 і вище залежно від того, де ви жили. Ці різні системи назвали кодовими сторінками. Так, наприклад, в Ізраїлі DOS використовував кодову сторінку з номером 862, в той час як грецькі користувачі використовували сторінку з номером 737. Вони були одними і тими ж нижче 128, але відрізнялися від 128, де і перебували всі ці символи. Національні версії MS-DOS підтримували безліч цих кодових сторінок, звертаючись з усіма мовами, починаючи з англійської та закінчуючи ісландським, і було навіть кілька "багатомовних" кодових сторінок, які могли зробити Есперанто і Галісійська (прим. Пер.: Галісійська мова належить до романської групи мов, поширений в Іспанії, носіїв 4 млн. чол) на одному і тому ж комп'ютері! Але отримати, скажімо, іврит і грецький на одному і тому ж комп'ютері було абсолютно неможливо, якщо тільки ви не написали вашу власну програму, яка показувала все, використовуючи графіку з побітовим відображенням, тому що для єврейського і грецького були потрібні різні кодові сторінки з різними інтерпретаціями старших чисел.

Тим часом в Азії, беручи до уваги той факт, що азіатські алфавіти мають тисячі букв, які ніколи б не змогли вміститися в 8 бітів, ця проблема вирішувалася заплутаною системою DBCS, "багатобайтових набір символів" (double byte character set), в якому деякі символи зберігалися в одному байті, а інші займали два. Було дуже легко пересуватися по рядку вперед, але абсолютно неможливо пересуватися назад. Програмісти не могли використовувати для переміщення вперед і назад s ++ і s--, і замість цього повинні були викликати спеціальні функції, які знали, як мати справу з цим безладом.

Проте, більшість людей закривало очі на те, що байт був символом і символ був 8 бітами і, поки вам не доводилося переміщати рядок з одного комп'ютера на інший, або якщо ви не говорили більше, ніж на одній мові, це працювало. Але, звичайно, як тільки масово став використовуватися Інтернет, стало звичайною справою переносити рядки з одного комп'ютера на інший. Хаос в цьому питанні був подоланий за допомогою Unicode.

Unicode

Unicode був сміливою спробою створити єдиний набір символів, який включав би всі реальні системи письма, що існують на планеті, а також деякі придумана. Деякі люди мають неправильне уявлення, що Unicode - це звичайний 16-бітовий код, де кожен символ займає 16 біт і тому є 65,536 можливих символів. Насправді це не вірно. Це самий поширене помилкове уявлення про Unicode.

Фактично, Unicode містить незвичайний підхід до розуміння поняття символ. До цього часу ми припускали, що символи відображаються на набір якихось бітів, які ви можете зберігати на диску або в пам'яті:

A - & gt 0100 0001

В Unicode символ відображається на щось, зване кодової точкою (code point), яка є всього лише теоретичним поняттям. Як ця кодова точка представлена ​​в пам'яті або на диску - це окрема історія. В Unicode буква A це всього лише платонова ідея (ейдос) (прим. Пер .: поняття філософії Платона, ейдоси - це ідеальні сутності, позбавлені тілесності і є справді об'єктивною реальністю, що знаходяться поза конкретних речей і явищ).

  A Ета платонова  A відрізняється від B, і відрізняється від a, але це та ж сама  A, що і A   і A. Ідея, що   А в шрифті Times New Roman є тим же самим, що і А в шрифті Helvetica, але відрізняється від малої "a", чи не здається занадто спірною в розумінні людей. Але з точки зору комп'ютерних наук і з точки зору мови саме визначення літери суперечливо. Німецька буква ß - етонастоящая буква або всього лише химерний спосіб написати ss? Якщо написання букви, що стоїть в кінці слова, змінюється, вона стає іншою буквою? Іврит говорить так, арабська говорить немає. Так чи інакше, розумні люди в консорціумі Unicode зрозуміли це, після великої кількості політичних дебатів, і ви не повинні хвилюватися про це. Всі вже зрозуміли до нас.

Кожній Платонової букві в кожному алфавіті консорціумом Unicode було призначено чарівне число, яке записується так, як це: U + 0645. Це чарівне число називають кодовою точкою. U + означає "Unicode", а числа є шестнадцатерічнимі. Число U + FEC9 є арабської буквою Аїн (Ain). Англійська літера A відповідає U + 0041.

Насправді немає ніякої межі для кількості букв, які можуть визначатися через Unicode, і насправді вони вже переступили за межі 65,536, так що не кожна буква з Unicode може дійсно стискатися в два байта.



Для кирилиці в UNICODE відведений діапазон кодів від 0x0400 до 0x04FF. У даній таблиці наведено лише частина знаків цього діапазону, проте стандартом визначено більшість кодів цього діапазону.

Уявімо, що ми маємо рядок:

Привіт! яка, в Unicode, відповідає цим семи кодовою точкам: U + 041F U + 0440 U + 0438 U + 0432 U + 0435 U + 0442 U + 0021

Всього лише набір кодових точок. Числа в дійсності.

Щоб дізнатися, як буде виглядати текстовий файл у форматі Unicode, можна запустити програму notepad в Windows, вставити цей рядок і при збереженні текстового файлу вибрати кодування Unicode.

Програма пропонує збереження в трьох різновидах кодувань Unicode. Перший варіант являє собою спосіб записи з молодшим байтом попереду (little endian), другий зі старшим байтом попереду (big endian). Який з варіантів є правильним?

Ось як виглядає дамп файлу з рядком "Привіт!", Який було збережено в форматі Unicode (big endian):

А так виглядає дамп файлу з рядком "Привіт!", Який було збережено в форматі Unicode (little endian):

А так виглядає дамп файлу з рядком "Привіт!", Який було збережено в форматі Unicode (UTF-8):

Ранні реалізації хотіли бути в змозі зберігати кодові точки Unicode в форматі з першим старшим байтом і першим молодшим байтом (high-endian or low-endian), в залежності від того, з яким форматом саме їх процесор працював швидше. Тоді виникло два способи зберігати Unicode. Це призвело до появи вигадливого угоди про зберігання коду \\ uFFFE на початку кожного рядка Unicode. Цю сигнатуру називають міткою порядку байтів (byte order mark). Якщо ви поміняєте місцями ваші старший і молодший байти, то на початку має стояти \\ uFFFE, і людина, що читає вашу рядок, буде знати, що він повинен поміняти байти в кожній парі місцями. Дана сигнатура є зарезервованої в стандарті Unicode.

У стандарті Unicode написано, що порядок байт за замовчуванням є або big endian, або little endian. Дійсно, обидва порядку є правильним, і розробники систем самі вибирають собі один з них. Не варто турбуватися, якщо ваша система обмінюється даними з іншою системою і обидві використовують little endian.

Однак, якщо ваша Windows обмінюється даними з UNIX-сервером, який використовує big endian, одна з систем повинна здійснювати перекодування. В цьому випадку стандарт Unicode говорить, що можна вибрати будь-який з наступних способів вирішення проблеми:

  1. Коли дві системи, що використовують різний порядок уявлення байт в Unicode, обмінюються даними (не використовуючи якихось спеціальних протоколів), то порядок байт повинен бути big endian. У стандарті це називається канонічним (canonical)  порядком байт.
  2. Кожен рядок Unicode повинна починатися з коду \\ uFEFF. Код \\ uFFFE, який є "перевертанням" знака порядку. Тому якщо одержувач бачить в якості першого символу код \\ uFEFF, то це означає, що байти знаходяться в перевернутому (little endian) порядку. Проте, в реальності, не кожна рядок Unicode має на початку мітку порядку байтів.

Другий спосіб є більш універсальним і кращим.

Якийсь час здавалося, що всі задоволені, але англомовні програмісти розглядали в основному англійський текст і рідко використовували кодові точки вище U + 00FF. За однією тільки цієї причини Unicode багатьма ігнорувався протягом декількох років.

Спеціально для цього була винайдена блискуча концепція UTF-8.

UTF-8

UTF-8 був іншою системою зберігання вашої послідовності кодових точок Unicode, тих самих U + чисел, використовуючи ті ж 8 бітів в пам'яті. В UTF-8 кожна кодова точка з номерами від 0 до 127 зберігалися в єдиному байті.

По суті, це кодування зі змінною кількістю кодують байтів для зберігання використовується 2, 3, і, фактично, до 6 байтів. Якщо символ належить набору ASCII (код в інтервалі 0x00-0x7F), то він кодується так само як в ASCII одним байтом. Якщо юнікод символу більше або дорівнює 0x80, то його біти упаковуються в послідовність байтів за таким правилом:

Можна помітити, що якщо байт починається з нульового біта, то це однобайтовий символ ASCII. Якщо байт починається з 11 ..., то це стартовий байт несколькобайтовой послідовності, що кодує символ, число головних одиничок якого дорівнює кількості байт в послідовності. Якщо байт починається з 10 ..., то це серійний «транспортний» байт з послідовності байтів, кількість яких було визначено стартовим байтом. Ну а біти Unicode символу упаковуються в «транспортні» біти стартового і серійних байтів, позначені в таблиці як послідовність «xx..x».

У змінному кількості кодують байт можна переконатися по нижчеподаному дампи файлів.

Дамп файлу з рядком "Hello!", Який було збережено в форматі Unicode (UTF-8):

Дамп файлу з рядком "Привіт!", Який було збережено в форматі Unicode (UTF-8):

Приємним побічним ефектом цього є те, що англійський текст виглядає в UTF-8 точно те саме, як і в ASCII, таким чином американці навіть не помічають, що щось не так. Тільки вся інша частина світу повинна долати перешкоди. Конкретно, Hello, то, яке було U + 0048 U + 0065 U + 006C U + 006C U + 006F, тепер буде збережено в тих же 48 65 6C 6C 6F, так само як і в ASCII, і ANSI, і будь-якому іншому наборі символів OEM на планеті. Якщо ж ви настільки сміливі, щоб використовувати діакритичні символи або грецькі літери або літери Klingon, ви повинні будете використовувати кілька байтів для зберігання єдиною кодової точки, але американці ніколи цього не помітять. UTF-8 також має гарну особливість: старий код, необізнана про новий формат рядків, і обробляє рядки з нульовому байтом в кінці рядка, що не буде усікати рядки.

Інші кодування Unicode

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

Насправді є ще цілий набір інших способів закодувати Unicode. Є щось, зване UTF-7, яке сильно схожий на UTF-8, але гарантує, що старший біт завжди буде нулем. Ще є UCS-4, який зберігає кожну кодову точку в 4 байтах і гарантує, що абсолютно всі символи будуть збережені в однаковому числі байтів, але таке марнотратство пам'яті даремно не завжди виправдана такою гарантією.

Наприклад, ви можете закодувати в Unicode рядок Hello (U + 0048 U + 0065 U + 006C U + 006C U + 006F) в кодуванні ASCII, Або в старій грецької кодуванні OEM, або в єврейській кодуванні ANSI, або в будь-який з кількох сотень кодувань, які були винайдені до наших днів, з однією проблемою: деякі з символів можуть не відображатися! Якщо немає ніякого еквівалента для кодової точки Unicode, для якої ви намагаєтеся знайти еквівалент в будь-якої кодової таблиці, Для якої ви намагаєтеся зробити перетворення, ви зазвичай отримуєте невеликий знак питання:? або, якщо ви дійсно хороший програміст, то квадратик.

є сотні традиційних кодувань, Які можуть правильно зберігати тільки деякі кодові точки і замінювати всі інші кодові точки знаками. Наприклад, деякі популярні кодування англійського тексту - Windows 1 252 (стандарт Windows 9x для західноєвропейських мов) і ISO-8859-1, він же Латинський-1 (також придатний для будь-якого західноєвропейського мови). Але спробуйте перетворити російські або єврейські букви в цих кодуваннях, і ви отримаєте неабияку кількість знаків питання. Відмінною рисою UTF 7, 8, 16, і 32 є їх здатність правильно зберігати будь-яку кодову точку.

32 бітні кодові точки для символів Unicode в Java

У версію Java 2 5.0 внесені суттєві доповнення в типи Character і String для підтримки 32 бітних символів Unicode. У минулому всі символи Unicode могли зберігатися в шістнадцяти бітах, які дорівнюють розміру значення типу char (і розміром значення, що міститься в об'єкті типу Character), оскільки ці значення лежали в діапазоні від 0 до FFFF. Але з деякого часу набір символів Unicode було розширено, і тепер вимагає більше 16 біт для зберігання символу. Нова версія  наборів символів Unicode включає в себе символи, що лежать в діапазоні від 0 до 10FFFF.

Кодова точка або позиція (code point), кодова одиниця або кодове значення (code unit) і додатковий символ (supplemental character). Стосовно до мови Java кодова точка - це код символу з діапазону від 0 до 10FFFF. У мові Java термін "кодова одиниця" використовується для посилання на 16-бітові символи. Символи, що мають значення, більші, ніж FFFF, називаються додатковими.

Розширення набору символів Unicode створило фундаментальні проблеми для мови Java. Оскільки у додаткового символу значення більше, ніж може вмістити тип char, потрібні були деякі засоби для зберігання і обробки додаткових символів. У версії Java 2 5.0 ця проблема вирішена двома способами. По-перше, мова Java використовує два значення типу char для подання додаткового символу. Перше з них називається верхнім сурогатом (high surrogate), а друге - нижнім сурогатом (low surrogate). Розроблено нові методи, такі як codePointAt (), для перетворень кодових точок в додаткові символи і назад.

По-друге, в мові Java перевантажені деякі з існуючих раніше методів в класах Character і String. У перевантажених варіантах методів використовуються дані типу int замість char. Оскільки розмір змінної або константи типу int досить великий для розміщення будь-якого символу як одиничного значення, цей тип може використовуватися для зберігання будь-якого символу. Наприклад, у методу isDigit () тепер два варіанти, наведені далі:

Перший з наведених варіантів - початковий, другий - версія, що підтримує 32-бітові кодові точки. У всіх методів is ..., таких як isLetter () і isSpaceChar (), є версії для кодових точок, як і у методів to ..., таких як toUpperCase () і toLowerCase ().

На додаток до методів, перевантажених для обробки кодових точок, в мову Java, в клас Character включені нові методи, що забезпечують додаткову підтримку кодових точок. Деякі з них перераховані в таблиці:

  метод   опис
  static int charCount (int cp)    Повертає 1, якщо cp можна уявити одним значенням типу char. Повертає 2, якщо потрібно два значення типу char.
  static int codePointAt (CharSequence chars, int loc)
  static int codePointAt (char chars, int loc)   Повертає кодову точку для символьної позиції (location), заданої в параметрі loc
  static int codePointBefore (CharSequence chars, int loc)
  static int codePointBefore (char chars, int loc)   Повертає кодову точку для символьної позиції (location) попередньої заданої в параметрі loc
  static boolean isSupplementaryCodePoint (int cp)   Повертає true, якщо cp містить додатковий символ
  static boolean isHighSurrogate (char ch)   Повертає true, якщо ch містить допустимий верхній сурогат символу.
  static boolean isLowSurrogate (char ch)   Повертає true, якщо ch містить допустимий нижній сурогат символу.
  static boolean isSurrogatePair (char highCh, char lowCh)   Повертає true, якщо highCh і lowCh формують допустиму сурогатну пару.
  static boolean isValidCodePoint (int cp)   Повертає true, якщо cp містить допустиму кодову точку.
  static char toChars (int cp)   Перетворює кодову точку, що міститься в cp, в її еквівалент типу char, який може зажадати двох значень типу char. Повертає масив, який містить результат ... Дописати !!!
  static int toChars (int cp, char target, int loc) Перетворює кодову точку, що міститься в cp, в її еквівалент типу char, запам'ятовує результат в масиві target, починаючи з позиції, заданої в loc. Повертає 1, якщо cp можна уявити одним значенням типу char, і 2 в іншому випадку.
  static int toCodePoint (char ighCh, char lowCh)   Перетворює highCh і lowCh в їх еквівалентні кодові точки.

Для обробки кодових точок у класу String є ряд методів. В клас String також доданий наведений далі конструктор, який підтримує розширений набір символів Unicode:

String (int codePoints, int startIndex, int numChars)

У наведеній синтаксичної записи codePoints - це масив, що містить кодові точки. Формується результуючий рядок довжиною numChars, починаючи з позиції startIndex.

Деякі методи класу String, що забезпечують підтримку 32-бітних кодових точок для символів Unicode.

Висновок на консоль в Windows. команда chcp

більшість простих програм, Написаних на Java виводять будь-які дані на консоль. Висновок на консоль надає можливість вибрати кодування, в якій будуть виводитися дані вашої програми. Запустити вікно консолі можна натиснувши Пуск -\u003e Виконати, а потім ввести та запустити команду cmd. Висновок на консоль в Windows за замовчуванням проводиться в кодуванні Cp866. Щоб дізнатися в якому кодуванні виводяться символи в консолі, слід набрати команду chcp. За допомогою цієї ж команди можна задавати кодування, в якій будуть виводитися символи. Наприклад chcp 1251. Фактично дана команда створена тільки для того, щоб відображати або змінювати номер поточної кодової сторінки консолі.

Кодові сторінки, відмінні від Cp866 будуть правильно відображатися тільки в повноекранному режимі  або у вікні командного рядка, Що використовує шрифти TrueType. наприклад:


Для того, щоб побачити наступний висновок, необхідно змінити поточний шрифт на шрифт True Type. Підведіть курсор на заголовок вікна консолі, клацніть правою кнопкою  миші і виберіть опцію "Властивості". У вікні перейдіть на вкладку Шрифт і в ній виберіть шрифт, навпроти якого буде стояти подвійна буква Т. Вам буде запропоновано зберегти дану настройку для поточного вікна або для всіх вікон.

В результаті ваше вікно консолі набуде вигляду:

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

Системні властивості file.encoding, console.encoding і висновок на консоль

Перш ніж торкатися теми кодувань в початкових кодах програм слід чітко усвідомити, для чого призначені, і як працюють системні властивості file.encoding і console.encoding. Крім цих системних властивостей присутній ще ряд інших. Вивести на екран всі поточні системні властивості можна за допомогою наступної програми:

Import java.io. *; import java.util. *; public class getPropertiesDemo (public static void main (String args) (String s; for (Enumeration e = System.getProperties (). propertyNames (); e.hasMoreElements ();) (s = e.nextElement (). toString () ; System.out.println (s + "=" + System.getProperty (s));)))

Приклад виведення програми:

В операційній системі Windows за замовчуванням file.encoding = Сp1251. Однак існує ще одна властивість console.encoding, яке вказує, в якому кодуванні слід виробляти висновок на консоль. file.encoding вказує Java машині в якому кодуванні слід зчитувати вихідні коди програм, якщо кодування не вказано користувачем при компіляції. Фактично, дане системне властивість поширюється і на висновок за допомогою System.out.println ().

За замовчуванням ця властивість не встановлено. Ці системні властивості можна встановлювати і в вашій програмі, однак, для неї це вже буде не актуально, оскільки віртуальна машина користується тими значеннями, які були прочитані перед компіляцією і запуском вашої програми. Крім того, як тільки ваша програма відпрацьовує, системні властивості відновлюються. У цьому можна переконатися, запустивши двічі наступну програму.

   / ** * @author & lta href = "mailto: [Email protected]"& Gt Victor Zagrebin & lt / a & gt * / public class SetPropertyDemo (public static void main (String args) (System.out.println (" file.encoding before = "+ System.getProperty (" file.encoding ")); System. out.println ( "console.encoding before =" + System.getProperty ( "console.encoding")); System.setProperty ( "file.encoding", "Cp866"); System.setProperty ( "console.encoding", " Cp866 "); System.out.println (" file.encoding after = "+ System.getProperty (" file.encoding ")); System.out.println (" console.encoding after = "+ System.getProperty (" console .encoding "));))

Установка даних властивостей в програмі необхідна в тих випадках, коли воно використовується в подальшому коді до завершення роботи програми.

Відтворимо ще ряд типових прикладів, з проблемами, якими стикаються програмісти при виведенні. Припустимо, у нас є наступна програма:

Public class CyryllicDemo (public static void main (String args) (String s1 = ""; String s2 = ""; System.out.println (s1); System.out.println (s1);)) Крім цієї програми будемо оперувати додатковими факторами:

  • команда компіляції;
  • команда запуску;
  • кодування вихідного коду програми (встановлюється в більшості текстових редакторів);
  • кодування виведення на консоль (Використовується Cp866 за замовчуванням або встановлюється за допомогою команди chcp);
  • видимий висновок у вікні консолі.

javac CyryllicDemo.java

java CyryllicDemo

Кодування файлу: Cp1251

Кодування консолі: Cp866

висновок:

└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘▄█┌▌▐ ▀

рстуфхцчшщ'иьеюяЁёЄєЇїЎў °∙№√ ·¤■

javac CyryllicDemo.java

Кодування файлу: Cp866

Кодування консолі: Cp866

висновок:

CyryllicDemo.java:5: warning: unmappable character for encoding Cp1251

String s1 = "АБВГДЕЖЗІЙКЛМНОПРСТУФХЦЧ? ЩЬИ'ЕЮЯ";

javac CyryllicDemo.java -encoding Cp866

java -

Кодування файлу:Cp 866

Кодування консолі: Cp866

висновок:

АБВГДЕЖЗІЙКЛМНОПРСТУФХЦЧШЩЬИ'ЕЮЯ

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

javac CyryllicDemo.java -encoding Cp1251

java -Dfile.encoding = Cp866 CyryllicDemo

Кодування файлу: Cp1251

Кодування консолі: Cp866

висновок:

АБВГДЕЖЗІЙКЛМНОПРСТУФХЦЧШЩЬИ'ЕЮЯ

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

Особливо слід звернути увагу на проблему "Куди поділася буква Ш?" З другої серії запусків. Ще уважніше до цієї проблеми слід ставитися, якщо ви заздалегідь не знаєте, який текст буде зберігатися в виведеної рядку, і по наївності зробите компіляцію без завдання кодування. Якщо у вас дійсно в рядку не буде літери Ш, то компіляція виконається вдало і запуск теж. І на цьому ви навіть забудете, що втрачаєте дрібниця (букву Ш), яка може потенційно зустрітися виведеної рядку і неминуче призведе до подальших помилок.

У третій і четвертій серії при компіляції і запуску використовуються ключі: -encoding Cp866 і -Dfile.encoding = Cp866. Ключ -encoding вказує, в якому кодуванні слід зчитувати файл з вихідним кодом програми. Ключ -Dfile.encoding = Cp866 вказує в якому кодуванні слід виробляти висновок.

Unicode префікс \\ u і російські символи в початкових кодах

У мові Java для запису символів в форматі Unicode існує спеціальний префікс \\ u, а наступні за ним чотири шістнадцяткові цифри задають сам символ. Наприклад, \\ u2122 - це символ торгової марки (™). Така форма запису висловлює символ будь-якого алфавіту за допомогою цифр і префікса - символів, які містяться в стабільному діапазоні кодів від 0 до 127, який не зачіпається при перекодуванні вихідного коду. І, теоретично, в додатку або аплетів на мові Java можна використовувати будь-який символ в форматі Unicode, проте чи буде він відображатися коректно на екрані дисплея і, чи буде він відображатися взагалі, залежить від багатьох чинників. Для аплетов має значення тип браузера, а для програм і аплетів має значення тип операційної системи  і кодування, в якій написаний вихідний код програми.

Наприклад, на комп'ютерах, що працюють під управлінням американської версії системи Windows, За допомогою мови Java можна виводити на екран японські ієрогліфи через питання інтернаціоналізації.

Як другий приклад можна привести цілком часту помилку програмістів. Багато хто думає, що завдання російських символів в Unicode форматі з допомогою префікса \\ u в вихідному коді програми може вирішити проблему виведення російських символів при будь-яких обставинах. Адже віртуальна машина Java переводить вихідний код програми в Unicode. Однак перш ніж здійснити переклад в Unicode віртуальна машина повинна знати, в якому кодуванні написаний вихідний код вашої програми. Адже ви можете написати програму і в кодуванні Cp866 (DOS) і в Сp1251 (Windows), що типово для даної ситуації. У тому випадку, якщо ви не вказали кодування, віртуальна машина Java зчитує ваш файл з вихідним кодом програми в тій кодуванні, яка вказана в системній властивості file.encoding.

Однак повернемося до стандартних параметрів, і будемо вважати що file.encoding = Сp1251, а висновок на консоль виробляється в Cp866. Ось саме в цьому випадку виходить наступна ситуація: припустимо у вас є файл в кодуванні Сp1251:

файл MsgDemo1.java

Public class MsgDemo1 (public static void main (String args) (String s = "\\ u043A \\ u043E" + "\\ u0434 \\ u0438 \\ u0440 \\ u043E \\ u0432" + "\\ u043A \\ u0430"; System.out.println (s );))

І ви очікуєте, що на консоль виведеться слово "кодування", однак отримуєте:

Справа в тому, що коди з префіксом \\ u, перераховані в програмі дійсно кодують потрібні кириличні символи в кодової таблиці Unicode, Однак вони розраховані на те, що вихідний код вашої програми буде лічений в кодуванні Cp866 (DOS). За замовчуванням, же в системних властивостях вказано кодування Сp1251 (file.encoding = Сp1251). Природно, перше і неправильне, що спадає на думку - поміняти кодування файлу з вихідним кодом програми в текстовому редакторі. Але це ні до чого не приведе. Віртуальна машина Java все одно буде зчитувати ваш файл в кодуванні Сp1251, а коди \\ u розраховані на Cp866.

З цієї ситуації є три виходи. Перший варіант - використовувати ключ -encoding на етапі компіляції і -Dfile.encoding на етапі запуску програми. В цьому випадку ви примусово вказуєте віртуальній машині Java, щоб вона зчитувала файл з вихідним кодом в заданій кодуванні і виводила в заданій кодуванні.



Як видно з висновку на консолі, при компіляції повинен задаватися додатковий параметр -encoding Cp866, а при запуску повинен задаватися параметр -Dfile.encoding = Cp866.

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

Для перетворення потоку байт byte в рядок String і назад, в класі String є такі можливості: конструктор String (byte bytes, String enc), який отримує на вхід потік байт із зазначенням їх кодування; якщо кодування опустити, то вона буде прийнята кодування за замовчуванням з системного властивості file.encoding. Метод getBytes (String enc) повертає потік байт, записаних у зазначеній кодуванні; кодування також можна опустити і буде прийнята кодування за замовчуванням з системного властивості file.encoding.

приклад:
  файл MsgDemo2.java

Import java.io.UnsupportedEncodingException; public class MsgDemo2 (public static void main (String args) throws UnsupportedEncodingException (String str = "\\ u043A \\ u043E" + "\\ u0434 \\ u0438 \\ u0440 \\ u043E \\ u0432" + "\\ u043A \\ u0430"; byte b = str. getBytes ( "Cp866"); String str2 = new String (b, "Cp1251"); System.out.println (str2);))

Результат виведення програми:



Цей спосіб є менш гнучким в тому випадку, якщо ви орієнтуєтеся на те, що кодування в системній властивості file.encoding не зміниться. Однак цей спосіб може стати самим гнучким, якщо проводити опитування системного властивості file.encoding, і підставляти отримане значення кодування при формуванні рядків у вашій програмі. При використанні даного способу  слід уважно ставитися до того, що не всі сторінки виконують однозначне перетворення byte char.

Третій спосіб полягає в тому, щоб підібрати коректні Unicode коди для виведення слова "кодування" з розрахунку, що файл буде зчитуватися в кодуванні за замовчуванням - Cp1251. Для цих цілей існує спеціальна утиліта native2ascii.

Ця утиліта входить до складу Sun JDK і призначена для перетворення вихідних текстів до ASCII-виду. При запуску без параметрів, працює зі стандартним входом (stdin), а не виводить підказку по ключам, як інші утиліти. Це призводить до того, що багато хто і не здогадуються про необхідність вказівки параметрів (крім, тих, хто завітав до документації). Тим часом цю утиліту для правильної роботи  необхідно, як мінімум, вказати використовувану кодування за допомогою ключа -encoding. Якщо цього не зробити, то буде використана кодування за замовчуванням (file.encoding), що може дещо розходиться з очікуваною. В результаті, отримавши невірні коду букв (через невірну кодування), можна витратити багато часу на пошук помилок в абсолютно правильному коді.

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



Таким чином, якщо ви примусово не вказується кодування для віртуальної машини  Java при компіляції і при запуску, а кодуванням за замовчуванням (file.encoding) є Cp1251, то вихідний код програми повинен виглядати наступним чином:

файл MsgDemo3.java

Public class MsgDemo3 (public static void main (String args) (String s = "\\ u0404 \\ u00AE" + "\\ u00A4 \\ u0401 \\ u0430 \\ u00AE \\ u045E" + "\\ u0404 \\ u00A0"; System.out.println (s );))

Використавши третій спосіб, можна зробити висновок: якщо кодування файлу з вихідним кодом в редакторі збіглася з кодуванням в системі, то повідомлення "кодування" з'явиться в нормальному вигляді.

Читання і запис в файл російських символів, виражених Unicode префіксом \\ u

Для читання даних, записаних як у форматі MBCS (використовуючи кодування UTF-8), так і в форматі Unicode, можна використовувати клас InputStreamReader з пакета java.io, підставляючи в його конструктор різні кодування. Для запису використовується OutputStreamWriter. В описі пакету java.lang написано, що кожна реалізація JVM Підтримується наступні кодування:

файл WriteDemo.java

Import java.io.Writer; import java.io.OutputStreamWriter; import java.io.FileOutputStream; import java.io.IOException; / ** * Висновок Unicode рядки в файл в заданій кодуванні. * @Author & lta href = "mailto: [Email protected]"& Gt Victor Zagrebin & lt / a & gt * / public class WriteDemo (public static void main (String args) throws IOException (String str =" \\ u043A \\ u043E "+" \\ u0434 \\ u0438 \\ u0440 \\ u043E \\ u0432 "+" \\ u043A \\ u0430 "; Writer out1 = new OutputStreamWriter (new FileOutputStream (" out1.txt ")," Cp1251 "); Writer out2 = new OutputStreamWriter (new FileOutputStream (" out2.txt ")," Cp866 "); Writer out3 = new OutputStreamWriter (new FileOutputStream ( "out3.txt"), "UTF-8"); Writer out4 = new OutputStreamWriter (new FileOutputStream ( "out4.txt"), "Unicode"); out1.write (str); out1.close (); out2.write (str); out2.close (); out3.write (str); out3.close (); out4.write (str); out4.close ();)) Компіляція: javac WriteDemo.java запуск: java WriteDemo

В результаті виконання програми має створитися чотири файли (out1.txt out2.txt out3.txt out4.txt) в каталозі запуску програми, кожен з яких буде містити слово "кодування" в різній кодуванні, що можна перевірити в текстових редакторах  або за допомогою перегляду дампа файлу.

Наступна програма буде зчитувати і виводити на екран вміст кожного зі створених файлів.

Файл ReadDemo.java import java.io.Reader; import java.io.InputStreamReader; import java.io.InputStream; import java.io.FileInputStream; import java.io.IOException; / ** * Читання Unicode символів  з файлу в заданій кодуванні. * @Author & lta href = "mailto: [Email protected]"& Gt Victor Zagrebin & lt / a & gt * / public class ReadDemo (public static void main (String args) throws IOException (String out_enc = System.getProperty (" console.encoding "," Cp866 "); System.out.write (readStringFromFile ( "out1.txt", "Cp1251", out_enc)); System.out.write ( "\\ n"); System.out.write (readStringFromFile ( "out2.txt", "Cp866", out_enc)); System. out.write ( "\\ n"); System.out.write (readStringFromFile ( "out3.txt", "UTF-8", out_enc)); System.out.write ( "\\ n"); System.out. write (readStringFromFile ( "out4.txt", "Unicode", out_enc));) public static byte readStringFromFile (String filename, String file_enc, String out_enc) throws IOException (int size; InputStream f = new FileInputStream (filename); size = f.available (); Reader in = new InputStreamReader (f, file_enc); char ch = new char; in.read (ch, 0, size); in.close (); return (new String (ch)). getBytes (out_enc);)) Компіляція: javac ReadDemo.java Запуск: java ReadDemo Результат виведення прог Рамі:

Особливо слід відзначити використання наступного рядка коду в даній програмі:

String out_enc = System.getProperty ( "console.encoding", "Cp866");

За допомогою методу getProperty здійснюється спроба прочитати значення системного властивості console.encoding, яке задає кодування, в якій будуть виводитися дані на консоль. Якщо ж така властивість не встановлено (найчастіше воно не встановлено), то змінної out_enc присвоїти "Cp866". І далі, змінна out_enc використовується там, де необхідно привести зчитану з файлу рядок до кодування, придатної для виведення на консоль.

Також виникає закономірне питання: "чому використовується System.out.write, а не System.out.println"? Як було описано вище, системне властивість file.encoding використовується не тільки для зчитування вихідного файлу, а й для виведення за допомогою System.out.println, що в даному випадку призведе до некоректного висновку.

Неправильне відображення кодування в програмах, орієнтованих на web

Програмісту насамперед слід знати: не має сенсу мати рядок, не знаючи, яке кодування вона використовує. Не існує такого поняття як "простий" (plain) текст в ASCII. Якщо у вас є рядок, в пам'яті, в файлі, або в повідомленні електронної пошти, Ви повинні знати, в який вона кодуванні, інакше ви не зможете її правильно інтерпретувати або показати користувачеві.

Майже всі традиційні проблеми типу "мій вебсайт схожий на тарабарщину" або "мої електронні листи не читаються, якщо я використовую символи з наголосами" лежать на відповідальності програміста, який не розуміє простого факту, що якщо ви не знаєте в якому кодуванні рядок UTF-8 або ASCII або ISO 8859-1 (Латинський-1) або Windows тисяча двісті п'ятьдесят дві (Західноєвропейський), ви просто не зможете вивести її правильно. Є більш ста кодувань символів вище кодової точки 127, і немає ніякої інформації для того, щоб з'ясувати, яка кодування потрібна. Як ми зберігаємо інформацію про те, яке кодування використовують рядки? Існують стандартні способи для зазначення цієї інформації. Для повідомлень електронної пошти ви повинні помістити в HTTP заголовок рядок

Content-Type: text / plain; charset = "UTF-8"

Для веб-сторінки оригінальна ідея була в тому, що веб-сервер сам буде посилати HTTP заголовок, перед самою сторінкою HTML. Але це викликає певні проблеми. Припустимо, що ви маєте великий веб-сервер з великою кількістю сайтів і сотнями сторінок, створених великою кількістю людей на величезній кількості різних мов, і всі вони не використовують специфічну кодування. Сам веб-сервер дійсно не може знати, яка кодування у кожного файлу, і тому не може послати заголовок із зазначенням Content-Type. Тому для вказівки правильного кодування в http заголовку залишалося тримати інформацію про кодування всередині html файлу шляхом вставки спеціального тега. Сервер б в такому випадку зчитував найменування кодування з мета-тега і поміщав її в HTTP заголовок.

Виникає слушне запитання: «як почати зчитувати файл HTML, поки Ви не дізнаєтеся, яке кодування він використовує ?! На щастя, майже всі кодування використовують одну і ту ж таблицю символів з кодами від 32 до 127, і сам код HTML складається з цих символів, і ви можете навіть не зустріти в html файлі  інформацію про кодування, якщо він повністю складається з таких символів. Тому, в ідеалі, тег & ltmeta & gt із зазначенням кодування дійсно повинен бути в самій першому рядку в секції & lthead & gt, тому що як тільки веб-браузер побачить цю ознаку, він перестане розбирати сторінку і почне все заново, використовуючи ту кодування, яку ви задали.

   & Lthtml & gt & lthead & gt & ltmeta http-equiv = "Content-Type" content = "text / html; charset = utf-8" & gt

Що роблять веб-браузери, якщо вони не знаходять ніякого Content-Type, ні в заголовку http, ні в тезі Meta? Internet Explorer фактично робить дещо вельми цікаве: він пробує розпізнати кодування і мову, грунтуючись на частоті, з якою різні байти з'являються в типовому тексті в типових кодуваннях різних мов. Так як різні старі 8-байтові кодові сторінки по-різному розміщували національні символи в діапазоні між 128 і 255, і так як всі людські мови мають різні частотні ймовірності використання букв, такий підхід часто непогано спрацьовує.

Це дуже химерно, але це, здається, дійсно cрабативает досить часто і наївні автори веб-сторінок, які ніколи не знали, що вони потребували надання тега Content-Type в заголовку їх сторінок для того, щоб сторінки правильно відображалися, до того прекрасного дня , коли вони напишуть щось, що точно не відповідає типовому частотно-вероятностному розподілу букв їх рідної мови, і Internet Explorer вирішить, що це корейську мову і покаже її відповідним чином.

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

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

посилання:

  1. Joel Spolsky. The absolute minimum every software developer absolutely, positively must know about Unicode and character sets (No Excuses!) 08.10.2003 http://www.joelonsoftware.com/articles/Unicode.html
  2. Сергій Астахов.
  3. Сергій Семіхатов. . 08.2000 - 27.07.2005
  4. Хорстман К.С., Корнелл Г. Бібліотека професіонала. Java 2. Том 1. Основи. - М .: Видавничий будинок Вільямс, 2003. - 848 с
  5. Dan Chisholms. Java Programmer Mock Exams. Objective 2, InputStream and OutputStream Reader / Writer. Java Character Encoding: UTF and Unicode. http://www.jchq.net/certkey/1102_12certkey.htm
  6. Package java.io. JavaTM 2 Platform Standard Edition 6.0 API Specification.