Що таке кодування символів, як ANSI та Unicode, і чим вони відрізняються?

ASCII, UTF-8, ISO-8859 . Можливо, ви бачили ці дивні прізвиська, що плавають навколо, але що вони насправді означають? Прочитайте далі, коли ми пояснюємо, що таке кодування символів і як ці скорочення стосуються простого тексту, який ми бачимо на екрані.

Фундаментальні будівельні блоки

Коли ми говоримо про письмову мову, ми говоримо про букви, що є складовою частиною слів, які потім будують речення, абзаци тощо. Букви – це символи, що представляють звуки. Коли ви говорите про мову, ви говорите про групи звуків, які об’єднуються, утворюючи якесь значення. Кожна мовна система має складний набір правил і визначень, які регулюють ці значення. Якщо у вас є слово, воно марне, якщо ви не знаєте, з якої мови воно є, і не використовуєте його разом з іншими, хто розмовляє цією мовою.

(Порівняння сценаріїв Grantha, Tulu та Malayalam, Зображення з Вікіпедія )

У світі комп’ютерів ми використовуємо термін „персонаж”. Символ – це свого роду абстрактне поняття, яке визначається конкретними параметрами, але воно є основною одиницею значення. Латинське «А» – це не те саме, що грецьке «альфа» чи арабське «аліф», оскільки вони мають різний контекст – вони з різних мов і мають дещо різну вимову – тож ми можемо сказати, що це різні символи. Візуальне зображення символу називається «гліфом», а різні набори гліфів називаються шрифтами. Групи персонажів належать до “набору” або “репертуару”.

Коли ви набираєте абзац і змінюєте шрифт, ви не змінюєте фонетичні значення букв, ви змінюєте їхній вигляд. Це просто косметика (але не маловажна!). Деякі мови, як давньоєгипетська та китайська, мають ідеограми; вони представляють цілі ідеї замість звуків, і їх вимови можуть змінюватися в часі та на відстані. Якщо ви замінюєте один символ іншим, ви підмінюєте ідею. Це не просто зміна літер, це зміна ідеограми.

Кодування символів

Коли ви вводите щось на клавіатурі або завантажуєте файл, як комп’ютер знає, що відображати? Для цього призначене кодування символів. Текст на вашому комп’ютері насправді не букви, це ряд спарених буквено-цифрових значень. Кодування символів діє як ключ, значення якого відповідають яким символам, подібно до того, як орфографія диктує, які звуки відповідають яким буквам. Код Морзе – це своєрідне кодування символів. Це пояснює, як групи довгих і коротких одиниць, такі як звукові сигнали, представляють символи. У азбуці Морзе символи – це лише англійські літери, цифри та крапки. Існує багато комп’ютерних кодувань символів, які перекладаються на літери, цифри, знаки наголосу, розділові знаки, міжнародні символи тощо.

Часто в цій темі також використовується термін “кодові сторінки”. Вони, по суті, є кодуванням символів, як використовується певними компаніями, часто з невеликими змінами. Наприклад, кодова сторінка Windows 1252 (раніше відома як ANSI 1252) є модифікованою формою ISO-8859-1. Вони в основному використовуються як внутрішня система для посилання на стандартне та модифіковане кодування символів, характерне для тих самих систем. На початку кодування символів було не настільки важливим, оскільки комп’ютери не спілкувались між собою. З ростом популярності Інтернету, а мережами є звичним явищем, він стає все більш важливим у нашому повсякденному житті, навіть не усвідомлюючи цього.

Багато різних типів

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

Давайте розглянемо деякі з найбільш поширених.

(Уривок таблиці ASCII, Зображення з asciitable.com )

  • ASCII – Американський стандартний код для обміну інформацією є одним із старих кодувань символів. Спочатку він був розроблений на основі телеграфних кодів і розвивався з часом, щоб включати більше символів та деякі застарілі недруковані контрольні символи. Це, мабуть, настільки базове, наскільки це можливо з точки зору сучасних систем, оскільки воно обмежене латинським алфавітом без наголошених символів. Його 7-бітне кодування дозволяє мати лише 128 символів, тому у всьому світі використовується кілька неофіційних варіантів.
  • ISO-8859 – Найбільш вживаною групою кодування символів Міжнародної організації зі стандартизації є номер 8859. Кожне конкретне кодування позначається цифрою, яка часто має префікс описовим прізвищем, наприклад ISO-8859-3 (латинська-3), ISO-8859-6 (латинська / арабська). Це надмножина ASCII, що означає, що перші 128 значень у кодуванні збігаються з ASCII. Однак він 8-розрядний і дозволяє використовувати 256 символів, тому він будується звідти і включає набагато ширший набір символів, причому кожне конкретне кодування фокусується на різному наборі критеріїв. Латиниця-1 включала купу наголошених букв та символів, але пізніше була замінена переробленим набором під назвою Latin-9, що включає оновлені символи, такі як символ євро.

(Уривок тибетського сценарію, Unicode v4, з unicode.org )

  • Юнікод – Цей стандарт кодування націлений на універсальність. На даний момент він включає 93 сценарії, організовані в кілька блоків, і ще багато з них працюють. Юнікод працює інакше, ніж інші набори символів, оскільки замість прямого кодування гліфа кожне значення направляється далі до «кодової точки». Це шістнадцяткові значення, які відповідають символам, але самі гліфи надаються окремо програмою, наприклад, вашим веб-браузером. Ці кодові точки зазвичай зображуються наступним чином: U + 0040 (що перекладається як ‘@’ ). Конкретними кодуваннями за стандартом Unicode є UTF-8 та UTF-16. UTF-8 намагається забезпечити максимальну сумісність з ASCII. Він 8-розрядний, але дозволяє використовувати всі символи за допомогою механізму заміни та кількох пар значень на символ. UTF-16 втрачає ідеальну сумісність з ASCII для більш повної 16-бітової сумісності зі стандартом.
  • ISO-10646 – Це не фактичне кодування, а лише набір символів Unicode, який стандартизований ISO. Це в основному важливо, оскільки це репертуар символів, який використовується HTML. Деякі з більш розширених функцій, що надаються Unicode, що дозволяють здійснювати сортування та справа наліво поряд із сценаріями зліва направо, відсутні. Тим не менше, він дуже добре працює для використання в Інтернеті, оскільки дозволяє використовувати широкий спектр сценаріїв і дозволяє браузеру інтерпретувати гліфи. Це дещо полегшує локалізацію.

Яке кодування слід використовувати?

Ну, ASCII працює для більшості англомовних, але не для багатьох інших. Частіше ви бачите ISO-8859-1, який працює для більшості західноєвропейських мов. Інші версії ISO-8859 працюють для кирилиці, арабської, грецької та інших специфічних писемностей. Однак якщо ви хочете відобразити кілька сценаріїв в одному документі або на одній веб-сторінці, UTF-8 забезпечує набагато кращу сумісність. Це також дуже добре працює для людей, які використовують правильні знаки пунктуації, математичні символи або символи, що не містять манжети, такі як квадрати та прапорці .

(Кілька мов в одному документі, знімок екрана gujaratsamachar.com )

Однак у кожного набору є недоліки. Знаки пунктуації ASCII обмежені, тому він не працює неймовірно добре для друкарських правильних редагувань. Ви коли-небудь вводили копію / вставку із Word лише для того, щоб мати якусь дивну комбінацію гліфів? Це недолік ISO-8859, або, вірніше, його передбачувана взаємодія зі специфічними для ОС кодовими сторінками (ми розглядаємо ВАС, Microsoft!). Основним недоліком UTF-8 є відсутність належної підтримки при редагуванні та публікації додатків. Інша проблема полягає в тому, що браузери часто не інтерпретують і просто відображають позначку порядку байтів символу, закодованого UTF-8. Це призводить до відображення небажаних гліфів. І звичайно, декларування одного кодування та використання символів з іншого без належного декларування / посилання на них на веб-сторінці ускладнює браузерам їх правильну візуалізацію, а пошуковим системам – належним індексом.

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

What are Unicode, UTF-8, and UTF-16?

What’s the basis for Unicode and why the need for UTF-8 or UTF-16? I have researched this on Google and searched here as well, but it’s not clear to me. In VSS, when doing a file comparison, sometimes there is a message saying the two files have differing UTF’s. Why would this be the case? Please explain in simple terms.

@John: it’s a very nice introduction, but it’s not the ultimate source: It skips quite a few of the details (which is fine for an overview/introduction!)

The article is great, but it has several mistakes and represents UTF-8 in somewhat conservative light. I suggest reading utf8everywhere.org as a supplement.

9 Answers 9

Why do we need Unicode?

In the (not too) early days, all that existed was ASCII. This was okay, as all that would ever be needed were a few control characters, punctuation, numbers and letters like the ones in this sentence. Unfortunately, today’s strange world of global intercommunication and social media was not foreseen, and it is not too unusual to see English, العربية, 汉语, עִבְרִית, ελληνικά, and ភាសាខ្មែរ in the same document (I hope I didn’t break any old browsers).

But for argument’s sake, let’s say Joe Average is a software developer. He insists that he will only ever need English, and as such only wants to use ASCII. This might be fine for Joe the user, but this is not fine for Joe the software developer. Approximately half the world uses non-Latin characters and using ASCII is arguably inconsiderate to these people, and on top of that, he is closing off his software to a large and growing economy.

Therefore, an encompassing character set including all languages is needed. Thus came Unicode. It assigns every character a unique number called a code point. One advantage of Unicode over other possible sets is that the first 256 code points are identical to ISO-8859-1, and hence also ASCII. In addition, the vast majority of commonly used characters are representable by only two bytes, in a region called the Basic Multilingual Plane (BMP). Now a character encoding is needed to access this character set, and as the question asks, I will concentrate on UTF-8 and UTF-16.

Memory considerations

So how many bytes give access to what characters in these encodings?

  • UTF-8:
  • 1 byte: Standard ASCII
  • 2 bytes: Arabic, Hebrew, most European scripts (most notably excluding Georgian)
  • 3 bytes: BMP
  • 4 bytes: All Unicode characters
  • UTF-16:
  • 2 bytes: BMP
  • 4 bytes: All Unicode characters

It’s worth mentioning now that characters not in the BMP include ancient scripts, mathematical symbols, musical symbols, and rarer Chinese, Japanese, and Korean (CJK) characters.

If you’ll be working mostly with ASCII characters, then UTF-8 is certainly more memory efficient. However, if you’re working mostly with non-European scripts, using UTF-8 could be up to 1.5 times less memory efficient than UTF-16. When dealing with large amounts of text, such as large web-pages or lengthy word documents, this could impact performance.

Encoding basics

Note: If you know how UTF-8 and UTF-16 are encoded, skip to the next section for practical applications.

  • UTF-8: For the standard ASCII (0-127) characters, the UTF-8 codes are identical. This makes UTF-8 ideal if backwards compatibility is required with existing ASCII text. Other characters require anywhere from 2-4 bytes. This is done by reserving some bits in each of these bytes to indicate that it is part of a multi-byte character. In particular, the first bit of each byte is 1 to avoid clashing with the ASCII characters.
  • UTF-16: For valid BMP characters, the UTF-16 representation is simply its code point. However, for non-BMP characters UTF-16 introduces surrogate pairs. In this case a combination of two two-byte portions map to a non-BMP character. These two-byte portions come from the BMP numeric range, but are guaranteed by the Unicode standard to be invalid as BMP characters. In addition, since UTF-16 has two bytes as its basic unit, it is affected by endianness. To compensate, a reserved byte order mark can be placed at the beginning of a data stream which indicates endianness. Thus, if you are reading UTF-16 input, and no endianness is specified, you must check for this.

As can be seen, UTF-8 and UTF-16 are nowhere near compatible with each other. So if you’re doing I/O, make sure you know which encoding you are using! For further details on these encodings, please see the UTF FAQ.

Practical programming considerations

Character and string data types: How are they encoded in the programming language? If they are raw bytes, the minute you try to output non-ASCII characters, you may run into a few problems. Also, even if the character type is based on a UTF, that doesn’t mean the strings are proper UTF. They may allow byte sequences that are illegal. Generally, you’ll have to use a library that supports UTF, such as ICU for C, C++ and Java. In any case, if you want to input/output something other than the default encoding, you will have to convert it first.

Recommended, default, and dominant encodings: When given a choice of which UTF to use, it is usually best to follow recommended standards for the environment you are working in. For example, UTF-8 is dominant on the web, and since HTML5, it has been the recommended encoding. Conversely, both .NET and Java environments are founded on a UTF-16 character type. Confusingly (and incorrectly), references are often made to the “Unicode encoding”, which usually refers to the dominant UTF encoding in a given environment.

Library support: The libraries you are using support some kind of encoding. Which one? Do they support the corner cases? Since necessity is the mother of invention, UTF-8 libraries will generally support 4-byte characters properly, since 1, 2, and even 3 byte characters can occur frequently. However, not all purported UTF-16 libraries support surrogate pairs properly since they occur very rarely.

Counting characters: There exist combining characters in Unicode. For example, the code point U+006E (n), and U+0303 (a combining tilde) forms ñ, but the code point U+00F1 forms ñ. They should look identical, but a simple counting algorithm will return 2 for the first example, and 1 for the latter. This isn’t necessarily wrong, but it may not be the desired outcome either.

Comparing for equality: A, А, and Α look the same, but they’re Latin, Cyrillic, and Greek respectively. You also have cases like C and Ⅽ. One is a letter, and the other is a Roman numeral. In addition, we have the combining characters to consider as well. For more information, see Duplicate characters in Unicode.

Surrogate pairs: These come up often enough on Stack Overflow, so I’ll just provide some example links: