utf 8 и utf 16 чем отличаются

Как работают кодировки текста. Откуда появляются «кракозябры». Принципы кодирования. Обобщение и детальный разбор

Данная статья имеет цель собрать воедино и разобрать принципы и механизм работы кодировок текста, подробно этот механизм разобрать и объяснить. Полезна она будет тем, кто только примерно представляет, что такое кодировки текста и как они работают, чем отличаются друг от друга, почему иногда появляются не читаемые символы, какой принцип кодирования имеют разные кодировки.

Чтобы получить детальное понимание этого вопроса придется прочитать и свести воедино не одну статью и потратить довольно значительное время на это. В данном материале же это все собрано воедино и по идее должно сэкономить время и разбор на мой взгляд получился довольно подробный.

О чем будет под катом: принцип работы одно байтовых кодировок (ASCII, Windows-1251 и т.д.), предпосылки появления Unicode, что такое Unicode, Unicode-кодировки UTF-8, UTF-16, их отличия, принципиальные особенности, совместимость и несовместимость разных кодировок, принципы кодирования символов, практический разбор кодирования и декодирования.

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

Предпосылки Unicode

Начать думаю стоит с того времени когда компьютеризация еще не была так сильно развита и только набирала обороты. Тогда разработчики и стандартизаторы еще не думали, что компьютеры и интернет наберут такую огромную популярность и распространенность. Собственно тогда то и возникла потребность в кодировке текста. В каком то же виде нужно было хранить буквы в компьютере, а он (компьютер) только единицы и нули понимает. Так была разработана одно-байтовая кодировка ASCII (скорее всего она не первая кодировка, но она наиболее распространенная и показательная, по этому ее будем считать за эталонную). Что она из себя представляет? Каждый символ в этой кодировке закодирован 8-ю битами. Несложно посчитать что исходя из этого кодировка может содержать 256 символов (восемь бит, нулей или единиц 2 8 =256).

Первые 7 бит (128 символов 2 7 =128) в этой кодировке были отданы под символы латинского алфавита, управляющие символы (такие как переносы строк, табуляция и т.д.) и грамматические символы. Остальные отводились под национальные языки. То есть получилось что первые 128 символов всегда одинаковые, а если хочешь закодировать свой родной язык пожалуйста, используй оставшуюся емкость. Собственно так и появился огромный зоопарк национальных кодировок. И теперь сами можете представить, вот например я находясь в России беру и создаю текстовый документ, у меня по умолчанию он создается в кодировке Windows-1251 (русская кодировка использующаяся в ОС Windows) и отсылаю его кому то, например в США. Даже то что мой собеседник знает русский язык, ему не поможет, потому что открыв мой документ на своем компьютере (в редакторе с дефолтной кодировкой той же самой ASCII) он увидит не русские буквы, а кракозябры. Если быть точнее, то те места в документе которые я напишу на английском отобразятся без проблем, потому что первые 128 символов кодировок Windows-1251 и ASCII одинаковые, но вот там где я написал русский текст, если он в своем редакторе не укажет правильную кодировку будут в виде кракозябр.

Думаю проблема с национальными кодировками понятна. Собственно этих национальных кодировок стало очень много, а интернет стал очень широким, и в нем каждый хотел писать на своем языке и не хотел чтобы его язык выглядел как кракозябры. Было два выхода, указывать для каждой страницы кодировки, либо создать одну общую для всех символов в мире таблицу символов. Победил второй вариант, так создали Unicode таблицу символов.

Небольшой практикум ASCII

Возможно покажется элементарщиной, но раз уж решил объяснять все и подробно, то это надо.

Вот таблица символов ASCII:

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Тут имеем 3 колонки:

Unicode

С предпосылками создания общей таблицы для всех в мире символов, разобрались. Теперь собственно, к самой таблице. Unicode — именно эта таблица и есть (это не кодировка, а именно таблица символов). Она состоит из 1 114 112 позиций. Большинство этих позиций пока не заполнены символами, так что вряд ли понадобится это пространство расширять.

Разделено это общее пространство на 17 блоков, по 65 536 символов в каждом. Каждый блок содержит свою группу символов. Нулевой блок — базовый, там собраны наиболее употребляемые символы всех современных алфавитов. Во втором блоке находятся символы вымерших языков. Есть два блока отведенные под частное использование. Большинство блоков пока не заполнены.

Итого емкость символов юникода составляет от 0 до 10FFFF (в шестнадцатиричном виде).

Записываются символы в шестнадцатиричном виде с приставкой «U+». Например первый базовый блок включает в себя символы от U+0000 до U+FFFF (от 0 до 65 535), а последний семнадцатый блок от U+100000 до U+10FFFF (от 1 048 576 до 1 114 111).

Отлично теперь вместо зоопарка национальных кодировок, у нас есть всеобъемлющая таблица, в которой зашифрованы все символы которые нам могут пригодиться. Но тут тоже есть свои недостатки. Если раньше каждый символ был закодирован одним байтом, то теперь он может быть закодирован разным количеством байтов. Например для кодирования всех символов английского алфавита по прежнему достаточно одного байта например тот же символ «o» (англ.) имеет в юникоде номер U+006F, то есть тот же самый номер как и в ASCII — 6F в шестнадцатиричной и 111 в десятеричной. А вот для кодирования символа «U+103D5» (это древнеперсидская цифра сто) — 103D5 в шестнадцатиричной и 66 517 в десятеричной, тут нам потребуется уже три байта.

Решить эту проблему уже должны юникод-кодировки, такие как UTF-8 и UTF-16. Далее речь пойдет про них.

UTF-8 является юникод-кодировкой переменной длинны, с помощью которой можно представить любой символ юникода.

Давайте поподробнее про переменную длину, что это значит? Первым делом надо сказать, что структурной (атомарной) единицей этой кодировки является байт. То что кодировка переменной длинны, значит, что один символ может быть закодирован разным количеством структурных единиц кодировки, то есть разным количеством байтов. Так например латиница кодируется одним байтом, а кириллица двумя байтами.

Немного отступлю от темы, надо написать про совместимость ASCII и UTF

То что латинские символы и основные управляющие конструкции, такие как переносы строк, табуляции и т.д. закодированы одним байтом делает utf-кодировки совместимыми с кодировками ASCII. То есть фактически латиница и управляющие конструкции находятся на тех же самых местах как в ASCII, так и в UTF, и то что закодированы они и там и там одним байтом и обеспечивает эту совместимость.

Сравним на практике как будет выглядеть фраза «Hello мир» в трех разных кодировках: Windows-1251 (русская кодировка), ISO-8859-1 (кодировка западно-европейских языков), UTF-8 (юникод-кодировка). Суть данного примера состоит в том что фраза написана на двух языках. Посмотрим как она будет выглядеть в разных кодировках.

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются
В кодировке ISO-8859-1 нет таких символов «м», «и» и «р».

Теперь давайте поработаем с кодировками и разберемся как преобразовать строку из одной кодировки в другую и что будет если преобразование неправильное, или его нельзя осуществить из за разницы в кодировках.

Будем считать что изначально фраза была записана в кодировке Windows-1251. Исходя из таблицы выше запишем эту фразу в двоичном виде, в кодировке Windows-1251. Для этого нам потребуется всего только перевести из десятеричной или шестнадцатиричной системы (из таблицы выше) символы в двоичную.

01001000 01100101 01101100 01101100 01101111 00100000 11101100 11101000 11110000
Отлично, вот это и есть фраза «Hello мир» в кодировке Windows-1251.

Теперь представим что вы имеете файл с текстом, но не знаете в какой кодировке этот текст. Вы предполагаете что он в кодировке ISO-8859-1 и открываете его в своем редакторе в этой кодировке. Как сказано выше с частью символов все в порядке, они есть в этой кодировке, и даже находятся на тех же местах, но вот с символами из слова «мир» все сложнее. Этих символов в этой кодировке нет, а на их местах в кодировке ISO-8859-1 находятся совершенно другие символы. А конкретно «м» — позиция 236, «и» — 232. «р» — 240. И на этих позициях в кодировке ISO-8859-1 находятся следующие символы позиция 236 — символ «ì», 232 — «è», 240 — «ð»

Значит фраза «Hello мир» закодированная в Windows-1251 и открытая в кодировке ISO-8859-1 будет выглядеть так: «Hello ìèð». Вот и получается что эти две кодировки совместимы лишь частично, и корректно перекодировать строку из одной кодировке в другую не получится, потому что там просто напросто нет таких символов.

Тут и будут необходимы юникод-кодировки, а конкретно в данном случае рассмотрим UTF-8. То что символы в ней могут быть закодированы разным количеством байтов от 1 до 4 мы уже выяснили. Теперь стоит сказать что с помощью UTF могут быть закодированы не только 256 символов, как в двух предыдущих, а вобще все символы юникода

Работает она следующим образом. Первый бит каждого байта кодирующего символ отвечает не за сам символ, а за определение байта. То есть например если ведущий (первый) бит нулевой, то это значит что для кодирования символа используется всего один байт. Что и обеспечивает совместимость с ASCII. Если внимательно посмотрите на таблицу символов ASCII то увидите что первые 128 символов (английский алфавит, управляющие символы и знаки препинания) если их привести к двоичному виду, все начинаются с нулевого бита (будьте внимательны, если будете переводить символы в двоичную систему с помощью например онлайн конвертера, то первый нулевой ведущий бит может быть отброшен, что может сбить с толку).

Если первый бит не нулевой то символ кодируется несколькими байтами.

Для двухбайтовых символов первые три бита должны быть такие — 110

для трех-байтовых символов в первом байте ведущие биты — 1110

1110 1000 10 000111 10 1010101 — суммируем все кроме управляющих битов и получаем что в 16-ричной равно 103В5, U+103D5 — древнеперситдская цифра сто ( 10000001111010101 )

для четырех-байтовых символов в первом байте ведущие биты — 11110

11110 100 10 001111 10 111111 10 111111 — U+10FFFF это последний допустимый символ в таблице юникода ( 100001111111111111111 )

Теперь, при желании, можем записать нашу фразу в кодировке UTF-8.

UTF-16

UTF-16 также является кодировкой переменной длинны. Главное ее отличие от UTF-8 состоит в том что структурной единицей в ней является не один а два байта. То есть в кодировке UTF-16 любой символ юникода может быть закодирован либо двумя, либо четырьмя байтами. Давайте для понятности в дальнейшем пару таких байтов я буду называть кодовой парой. Исходя из этого любой символ юникода в кодировке UTF-16 может быть закодирован либо одной кодовой парой, либо двумя.

Начнем с символов которые кодируются одной кодовой парой. Легко посчитать что таких символов может быть 65 535 (2в16), что полностью совпадает с базовым блоком юникода. Все символы находящиеся в этом блоке юникода в кодировке UTF-16 будут закодированы одной кодовой парой (двумя байтами), тут все просто.

символ «o» (латиница) — 00000000 01101111
символ «M» (кириллица) — 00000100 00011100

Теперь рассмотрим символы за пределами базового юникод диапазона. Для их кодирования потребуется уже две кодовые пары (4 байта). И механизм их кодирования немного сложнее, давайте по порядку.

Для начала введем понятия суррогатной пары. Суррогатная пара — это две кодовые пары используемые для кодирования одного символа (итого 4 байта). Для таких суррогатных пар в таблице юникода отведен специальный диапазон от D800 до DFFF. Это значит, что при преобразовании кодовой пары из байтового вида в шестнадцатиричный вы получаете число из этого диапазона, то перед вами не самостоятельный символ, а суррогатная пара.

Чтобы закодировать символ из диапазона 1000010FFFF (то есть символ для которого нужно использовать более одной кодовой пары) нужно:

Для примера зашифруем символ, а потом расшифруем. Возьмем древнеперсидскую цифру сто (U+103D5):

Источник

Отличаются ли UTF-8, UTF-16 и UTF-32 количеством символов, которые они могут хранить?

ОК. Я знаю, что это выглядит как типичный

6 ответов

нет, это просто разные методы кодирования. Все они поддерживают кодирование одного и того же набора символов.

UTF-8 использует от одного до четырех байтов на символ в зависимости от того, какой символ вы кодируете. Символы в диапазоне ASCII занимают только один байт, в то время как очень необычные символы занимают четыре.

UTF-32 использует четыре байта на символ независимо от того, какой это символ, поэтому он всегда будет использовать больше места, чем UTF-8 для кодирования той же строки. Единственный преимущество заключается в том, что вы можете вычислить количество символов в строке UTF-32, только подсчитывая байты.

UTF-16 использует два байта для большинства символов, четыре байта для необычных.

нет символа Юникода, который может храниться в одной кодировке, но не в другой. Это просто потому, что допустимые символы Юникода были ограничены тем, что может быть сохранено в UTF-16 (который имеет наименьшую емкость из трех кодировок). Другими словами, UTF-8 и UTF-32 мог бы используется для представления более широкого диапазона символов, чем UTF-16, но они не. Подробнее читайте дальше.

UTF-8-это код переменной длины. Некоторые символы требуют 1 байт, некоторые требуют 2, Некоторые 3 и некоторые 4. Байты для каждого символа просто записываются один за другим как непрерывный поток байтов.

в то время как некоторые символы UTF-8 могут быть длиной 4 байта, UTF-8 невозможно закодировать 2^32 символа. Это даже не близко. Я попытаюсь объяснить причины этого.

в основном, есть компромисс между наличием многих характеры и иметь более короткие характеры. Если вы хотите 2^32 символов, они должны быть в среднем длиной 4 байта. Если вы хотите, чтобы все ваши символы были 2 байта или меньше, то вы не можете иметь более 2^16 символов. UTF-8 дает разумный компромисс: все ASCII символы (ASCII от 0 до 127) даны 1-байтовые представления, что отлично подходит для совместимости, но разрешено гораздо больше символов.

например, символ » A » представлен с использованием байта 65, и нет двух/трех/четырехбайтовых символов, первый байт которых равен 65. Иначе декодер не смог бы сказать. эти символы, кроме «А», за которыми следует что-то еще.

но UTF-8 ограничен еще больше. Это гарантирует, что кодировка более короткого символа никогда не появится в любом месте в кодировке более длинного символа. Например, ни один из байтов в 4-байтовом символе не может быть 65.

поскольку UTF-8 имеет 128 различных 1-байтовых символов (значения которых равны 0-127), все 2, 3 и 4-байтовые символы должны состоять исключительно из байтов в диапазоне 128-256. Это большое ограничение. Однако он позволяет строковым функциям, ориентированным на байты, работать практически без изменений. Например, C strstr() функция всегда работает так, как ожидалось, если ее входы являются допустимыми строками UTF-8.

UTF-16

UTF-16 также является кодом переменной длины; его символы потребляют либо 2, либо 4 байта. 2-байтовые значения в диапазоне 0xD800-0xDFFF зарезервированы для построения 4-байтовых символов, и все 4-байтовые символы состоят из два байта в диапазоне 0xD800-0xDBFF, а затем 2 байта в диапазоне 0xDC00-0xDFFF. По этой причине Unicode не назначает никаких символов в диапазоне U+D800-U+DFFF.

UTF-32

UTF-32-это код фиксированной длины, каждый символ имеет длину 4 байта. Хотя это позволяет кодировать 2^32 разных символа, в этой схеме разрешены только значения между 0 и 0x10FFFF.

емкость сравнение:

наиболее ограниченным является поэтому UTF-16! Формальное определение Юникода ограничило символы Юникода теми, которые могут быть закодированы с помощью UTF-16 (т. е. диапазон от U + 0000 до U+10FFFF без учета U+D800 до U+DFFF). UTF-8 и UTF-32 поддерживают все эти символы.

система UTF-8 фактически «искусственно» ограничена 4 байтами. Он может быть расширен до 8 байт без нарушения ограничений, которые я описал ранее, и это даст емкость 2^42. Исходная спецификация UTF-8 фактически допускала до 6 байт, что дает емкость 2^31. Но!—74—>RFC 3629 ограничил его 4 байтами, так как именно столько необходимо для покройте все, что делает UTF-16.

существуют другие (в основном исторические) схемы кодирования Unicode, в частности UCS-2 (который способен кодировать только U+0000 до U+FFFF).

UTF-8, UTF-16 и UTF-32 поддерживают полный набор кодовых точек unicode. Нет символов, которые поддерживаются одним, но не другим.

Что касается Бонусного вопроса » отличаются ли эти кодировки количеством символов, которые они могут быть расширены для поддержки?»И да, и нет. Способ кодирования UTF-8 и UTF-16 ограничивает общее количество кодовых точек, которые они могут поддерживать, менее чем 2^32. Однако консорциум Unicode не будет добавлять кодовые точки в UTF-32, которые не могут быть представлен в UTF-8 или UTF-16. Это нарушило бы дух стандартов кодирования и сделало невозможным гарантировать сопоставление один к одному от UTF-32 до UTF-8 (или UTF-16).

Я лично всегда проверяю Джоэл должности о unicode, кодировках и наборах символов, когда сомневаетесь.

все кодировки UTF-8/16/32 могут отображать все символы Юникода. См. сравнение Википедии кодировок Unicode.

эта статья IBM кодируйте XML-документы в UTF-8 очень полезно, и показывает если вы имеете выбор, то лучшее выбрать УТФ-8. Главным образом причины широкая поддержка инструмента, и УТФ-8 может обычно пройдите через системы, которые не знают unicode.

из раздела какие характеристики скажи на статья IBM:

и W3C и IETF имеют в последнее время стали более категоричны выбрав кодировку UTF-8 Во-первых, последний, и только иногда. Консорциум W3C характер Модель для Всемирной паутины 1.0: Основы гласит :» Когда уникальный требуется кодировка символов, кодировка должна быть UTF-8, UTF-16 или UTF-32. US-ASCII является вверх-совместимый с UTF-8 (an Строка US-ASCII также является UTF-8 строка, см. [RFC 3629]), и UTF-8 поэтому если совместимость с нами-ASCII-это необходимый.» В практика, совместимость с нами-ASCII так полезно это почти требование. W3C мудро объясняет, «В других ситуациях, таких как APIs, UTF-16 или UTF-32 могут быть больше соответствующий. Возможные причины выбор одного из них включает эффективность внутренней обработки и взаимодействие с другими процессы.»

как все уже говорили, UTF-8, UTF-16 и UTF-32 могут кодировать все кодовые точки Unicode. Однако вариант UCS-2 (иногда ошибочно называемый UCS-16) не может, и это тот, который вы найдете, например, в Windows XP / Vista.

посмотреть Википедия для получения дополнительной информации.

Edit: я ошибаюсь в Windows, NT был единственным, кто поддерживал UCS-2. Однако многие приложения Windows будут принимать одно слово в кодовой точке, как в UCS-2, поэтому вы, вероятно, найдете ошибки. См.еще одна статья в Википедии. (Спасибо JasonTrue)

Источник

Символы Unicode: о чём должен знать каждый разработчик

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Если вы пишете международное приложение, использующее несколько языков, то вам нужно кое-что знать о кодировке. Она отвечает за то, как текст отображается на экране. Я вкратце расскажу об истории кодировки и о её стандартизации, а затем мы поговорим о её использовании. Затронем немного и теорию информатики.

Введение в кодировку

Компьютеры понимают лишь двоичные числа — нули и единицы, это их язык. Больше ничего. Одно число называется байтом, каждый байт состоит из восьми битов. То есть восемь нулей и единиц составляют один байт. Внутри компьютеров всё сводится к двоичности — языки программирования, движений мыши, нажатия клавиш и все слова на экране. Но если статья, которую вы читаете, раньше была набором нулей и единиц, то как двоичные числа превратились в текст? Давайте разберёмся.

Краткая история кодировки

На заре своего развития интернет был исключительно англоязычным. Его авторам и пользователям не нужно было заботиться о символах других языков, и все нужды полностью покрывала кодировка American Standard Code for Information Interchange (ASCII).

ASCII — это таблица сопоставления бинарных обозначений знакам алфавита. Когда компьютер получает такую запись:

то с помощью ASCII он преобразует её во фразу «Hello world».

Один байт (восемь бит) был достаточно велик, чтобы вместить в себя любую англоязычную букву, как и управляющие символы, часть из которых использовалась телепринтерами, так что в те годы они были полезны (сегодня уже не особо). К управляющим символам относился, например 7 (0111 в двоичном представлении), который заставлял компьютер издавать сигнал; 8 (1000 в двоичном представлении) — выводил последний напечатанный символ; или 12 (1100 в двоичном представлении) — стирал весь написанный на видеотерминале текст.

В те времена компьютеры считали 8 бит за один байт (так было не всегда), так что проблем не возникало. Мы могли хранить все управляющие символы, все числа и англоязычные буквы, и даже ещё оставалось место, поскольку один байт может кодировать 255 символов, а для ASCII нужно только 127. То есть неиспользованными оставалось ещё 128 позиций в кодировке.

Вот как выглядит таблица ASCII. Двоичными числами кодируются все строчные и прописные буквы от A до Z и числа от 0 до 9. Первые 32 позиции отведены для непечатаемых управляющих символов.

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Проблемы с ASCII

Позиции со 128 по 255 были пустыми. Общественность задумалась, чем их заполнить. Но у всех были разные идеи. Американский национальный институт стандартов (American National Standards Institute, ANSI) формулирует стандарты для разных отраслей. Там утвердили позиции ASCII с 0 по 127. Их никто не оспаривал. Проблема была с остальными позициями.

Вот чем были заполнены позиции 128-255 в первых компьютерах IBM:

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Какие-то загогулины, фоновые иконки, математические операторы и символы с диакретическим знаком вроде é. Но разработчики других компьютерных архитектур не поддержали инициативу. Всем хотелось внедрить свою собственную кодировку во второй половине ASCII.

Все эти различные концовки назвали кодовыми страницами.

Что такое кодовые страницы ASCII?

Здесь собрана коллекция из более чем 465 разных кодовых страниц! Существовали разные страницы даже в рамках какого-то одного языка, например, для греческого и китайского. Как можно было стандартизировать этот бардак? Или хотя бы заставить его работать между разными языками? Или между разными кодовыми страницами для одного языка? В языках, отличающихся от английского? У китайцев больше 100 000 иероглифов. ASCII даже не может всех их вместить, даже если бы решили отдать все пустые позиции под китайские символы.

Эта проблема даже получила название Mojibake (бнопня, кракозябры). Так говорят про искажённый текст, который получается при использовании некорректной кодировки. В переводе с японского mojibake означает «преобразование символов».

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Пример бнопни (кракозябров).

Безумие какое-то.

Именно! Не было ни единого шанса надёжно преобразовывать данные. Интернет — это лишь монструозное соединение компьютеров по всему миру. Представьте, что все страны решили использовать собственные стандарты. Например, греческие компьютеры принимают только греческий язык, а английские отправляют только английский. Это как кричать в пустой пещере, тебя никто не услышит.

ASCII уже не удовлетворял жизненным требованиям. Для всемирного интернета нужно было создать что-то другое, либо пришлось бы иметь дело с сотнями кодовых страниц.

��� Если только ������ вы не хотели ��� бы ��� читать подобные параграфы. �֎֏0590֐��׀ׁׂ׃ׅׄ׆ׇ

Так появился Unicode

Unicode расшифровывают как Universal Coded Character Set (UCS), и у него есть официальное обозначение ISO/IEC 10646. Но обычно все используют название Unicode.

Этот стандарт помог решить проблемы, возникавшие из-за кодировки и кодовых страниц. Он содержит множество кодовых пунктов (кодовых точек), присвоенных символам из языков и культур со всего мира. То есть Unicode — это набор символов. С его помощью можно сопоставить некую абстракцию с буквой, на которую мы хотим ссылаться. И так сделано для каждого символа, даже египетских иероглифов.

Кто-то проделал огромную работу, сопоставляя каждый символ во всех языках с уникальными кодами. Вот как это выглядит:

Префикс U+ говорит о том, что это стандарт Unicode, а число — это результат преобразования двоичных чисел. Стандарт использует шестнадцатеричную нотацию, которая является упрощённым представлением двоичных чисел. Здесь вы можете ввести в поле что угодно и посмотреть, как это будет преобразовано в Unicode. А здесь можно полюбоваться на все 143 859 кодовых пунктов.

Уточню на всякий случай: речь идёт о большом словаре кодовых пунктов, присвоенных всевозможным символам. Это очень большой набор символов, не более того.

Осталось добавить последний ингредиент.

Unicode Transform Protocol (UTF)

UTF — протокол кодирования кодовых пунктов в Unicode. Он прописан в стандарте и позволяет кодировать любой кодовый пункт. Однако существуют разные типы UTF. Они различаются количеством байтов, используемых для кодировки одного пункта. В UTF-8 используется один байт на пункт, в UTF-16 — два байта, в UTF-32 — четыре байта.

Но если у нас есть три разные кодировки, то как узнать, какая из них применяется в конкретном файле? Для этого используют маркер последовательности байтов (Byte Order Mark, BOM), который ещё называют сигнатурой кодировки (Encoding Signature). BOM — это двухбайтный маркер в начале файл, который говорит о том, какая именно кодировка тут применена.

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

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Этот график построен в 2012-м, UTF-8 становилась доминирующей кодировкой. И всё ещё ею является.

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Что такое UTF-8 и как она работает?

UTF-8 кодирует с помощью одного байта каждый кодовый пункт Unicode с 0 по 127 (как в ASCII). То есть если вы писали программу с использованием ASCII, а ваши пользователи применяют UTF-8, они не заметят ничего необычного. Всё будет работать как задумано. Обратите внимание, как это важно. Нам нужно было сохранить обратную совместимость с ASCII в ходе массового внедрения UTF-8. И эта кодировка ничего не ломает.

Как следует из названия, кодовый пункт состоит из 8 битов (один байт). В Unicode есть символы, которые занимают несколько байтов (вплоть до 6). Это называют переменной длиной. В разных языках удельное количество байтов разное. В английском — 1, европейские языки (с латинским алфавитом), иврит и арабский представлены с помощью двух байтов на кодовый пункт. Для китайского, японского, корейского и других азиатских языков используют по три байта.

Если нужно, чтобы символ занимал больше одного байта, то применяется битовая комбинация, обозначающая переход — он говорит о том, что символ продолжается в нескольких следующих байтах.

И теперь мы, как по волшебству, пришли к соглашению, как закодировать шумерскую клинопись (Хабр её не отображает), а также значки emoji!

Подытожив сказанное: сначала читаем BOM, чтобы определить версию кодировки, затем преобразуем файл в кодовые пункты Unicode, а потом выводим на экран символы из набора Unicode.

Напоследок про UTF

Коды являются ключами. Если я отправлю ошибочную кодировку, вы не сможете ничего прочесть. Не забывайте об этом при отправке и получении данных. В наших повседневных инструментах это часто абстрагировано, но нам, программистам, важно понимать, что происходит под капотом.

Если HTML-документ не содержит упоминания кодировки, спецификация HTML5 предлагает такое интересное решение, как BOM-сниффинг. С его помощью мы по маркеру порядка байтов (BOM) можем определить используемую кодировку.

Это всё?

Unicode ещё не завершён. Как и в случае с любым стандартом, мы что-то добавляем, убираем, предлагаем новое. Никакие спецификации нельзя назвать «завершёнными». Обычно в год бывает 1-2 релиза, найти их описание можно здесь.

Если вы дочитали до конца, то вы молодцы. Предлагаю сделать домашнюю работу. Посмотрите, как могут ломаться сайты при использовании неправильной кодировки. Я воспользовался этим расширением для Google Chrome, поменял кодировку и попытался открывать разные страницы. Информация была совершенно нечитаемой. Попробуйте сами, как выглядит бнопня. Это поможет понять, насколько важна кодировка.

utf 8 и utf 16 чем отличаются. Смотреть фото utf 8 и utf 16 чем отличаются. Смотреть картинку utf 8 и utf 16 чем отличаются. Картинка про utf 8 и utf 16 чем отличаются. Фото utf 8 и utf 16 чем отличаются

Заключение

При написании этой статьи я узнал о Майкле Эверсоне. С 1993 года он предложил больше 200 изменений в Unicode, добавил в стандарт тысячи символов. По состоянию на 2003 год он считался самым продуктивным участником. Он один очень сильно повлиял на облик Unicode. Майкл — один из тех, кто сделал интернет таким, каким мы его сегодня знаем. Очень впечатляет.

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

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *