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

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

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

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

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

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


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

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

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

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


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

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



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

    • номер символа в десятичном формате
    • номер символа в шестнадцатиричном формате
    • представление самого символа.

    Итак, закодируем строку «ok» (англ.) в кодировке ASCII. Символ «o» (англ.) имеет позицию 111 в десятичном виде и 6F в шестнадцатиричном. Переведем это в двоичную систему — 01101111. Символ «k» (англ.) — позиция 107 в десятеричной и 6B в шестнадцатиричной, переводим в двоичную — 01101011. Итого строка «ok» закодированная в ASCII будет выглядеть так — 01101111 01101011. Процесс декодирования будет обратный. Берем по 8 бит, переводим их в 10-ичную кодировку, получаем номер символа, смотрим по таблице что это за символ.

    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


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

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

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


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

    Давайте возьмем символ «o»(англ.) из примера про ASCII выше. Помним что в таблице ASCII символов он находится на 111 позиции, в битовом виде это будет 01101111. В таблице юникода этот символ — U+006F что в битовом виде тоже будет 01101111. И теперь так, как UTF — это кодировка переменной длины, то в ней этот символ будет закодирован одним байтом. То есть представление данного символа в обеих кодировках будет одинаково. И так для всего диапазона символов от 0 до 128. То есть если ваш документ состоит из английского текста то вы не заметите разницы если откроете его и в кодировке UTF-8 и UTF-16 и ASCII (прим. в UTF-16 такие символы все равно будут закодированы двумя байтами, по этому вы не увидите разницы, если ваш редактор будет игнорировать нулевые байты), и так до момента пока вы не начнете работать с национальным алфавитом.

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


    В кодировке 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 символов (английский алфавит, управляющие символы и знаки препинания) если их привести к двоичному виду, все начинаются с нулевого бита (будьте внимательны, если будете переводить символы в двоичную систему с помощью например онлайн конвертера, то первый нулевой ведущий бит может быть отброшен, что может сбить с толку).

    01001000 — первый бит ноль, значит 1 байт кодирует 1 символ -> «H»

    01100101 — первый бит ноль, значит 1 байт кодирует 1 символ -> «e»

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

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

    11010000 10111100 — в начале 110, значит 2 байта кодируют 1 символ. Второй байт в таком случае всегда начинается с 10. Итого отбрасываем управляющие биты (начальные, которые выделены красным и зеленым) и берем все оставшиеся (10000111100), переводим их в шестнадцатиричный вид (043С) -> U+043C в юникоде равно символ «м».

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

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

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

    11110100 10001111 10111111 10111111 — 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 (то есть символ для которого нужно использовать более одной кодовой пары) нужно:

    1. из кода символа вычесть 10000(шестнадцатиричное) (это наименьшее число из диапазона 1000010FFFF)
    2. в результате первого пункта будет получено число не больше FFFFF, занимающее до 20 бит
    3. ведущие 10 бит из полученного числа суммируются с D800 (начало диапазона суррогатных пар в юникоде)
    4. следующие 10 бит суммируются с DC00 (тоже число из диапазона суррогатных пар)
    5. после этого получатся 2 суррогатные пары по 16 бит, первые 6 бит в каждой такой паре отвечают за определение того что это суррогат,
    6. десятый бит в каждом суррогате отвечает за его порядок если это 1 то это первый суррогат, если 0, то второй

    Разберем это на практике, думаю станет понятнее.

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

    1. 103D510000 = 3D5
    2. 3D5 = 0000000000 1111010101 (ведущие 10 бит получились нулевые приведем это к шестнадцатиричному числу, получим 0 (первые десять), 3D5 (вторые десять))
    3. 0 + D800 = D800 (1101100000000000) первые 6 бит определяют что число из диапазона суррогатных пар десятый бит (справа) нулевой, значит это первый суррогат
    4. 3D5 + DC00 = DFD5 (1101111111010101) первые 6 бит определяют что число из диапазона суррогатных пар десятый бит (справа) единица, значит это второй суррогат
    5. итого данный символ в UTF-16 — 1101100000000000 1101111111010101

    Теперь наоборот раскодируем. Допустим что у нас есть вот такой код — 1101100000100010 1101111010001000:

    1. переведем в шестнадцатиричный вид = D822 DE88 (оба значения из диапазона суррогатных пар, значит перед нами суррогатная пара)
    2. 1101100000100010 — десятый бит (справа) нулевой, значит первый суррогат
    3. 1101111010001000 — десятый бит (справа) единица, значит второй суррогат
    4. отбрасываем по 6 бит отвечающих за определение суррогата, получим 0000100010 1010001000 (8A88)
    5. прибавляем 10000 (меньшее число суррогатного диапазона) 8A88 + 10000 = 18A88
    6. смотрим в таблице юникода символ U+18A88 = Tangut Component-649. Компоненты тангутского письма.

    Спасибо тем кто смог дочитать до конца, надеюсь было полезно и не очень занудно.

    Вот некоторые интересные ссылки по данной теме:
    habr.com/ru/post/158895 — полезные общие сведения по кодировкам
    habr.com/ru/post/312642 — про юникод
    unicode-table.com/ru — сама таблица юникод символов

    Ну и собственно куда же без нее
    ru.wikipedia.org/wiki/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4 — юникод
    ru.wikipedia.org/wiki/ASCII — ASCII
    ru.wikipedia.org/wiki/UTF-8 — UTF-8
    ru.wikipedia.org/wiki/UTF-16 — UTF-16
    Поделиться публикацией

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 41

      +1
      Первая кодировка — это Код Бодо, ну это если не считать Морзянку
        +1
        3D5 = 00000000 1111010101 (ведущие 10 бит получились нулевые приведем это к шестнадцатиричному числу, получим 0 (первые десять), 3D5 (вторые десять))

        Десять или восемь?

        1101100000100010 — десятый бит нулевой, значит первый суррогат
        1101111010001000 — десятый бит единица, значит второй суррогат

        Что-то у меня в обоих случаях десятый бит равен нулю. Или я его не с той стороны отсчитываю? Тогда почему первые 6 отсчитывались с этой же стороны?
          0
          Десять или восемь?

          Чисто теоретически это без разницы, но лучше чтобы они были

          Что-то у меня в обоих случаях десятый бит равен нулю. Или я его не с той стороны отсчитываю? Тогда почему первые 6 отсчитывались с этой же стороны?

          Прошу прощения за мою оплошность.

          Спасибо что так внимательно прочитали)
          0
          > Вопрос с кодировками сейчас конечно уже потерял актуальность

          Винда научилась в юникодную кириллицу в терминале?
            0
            Теряет актуальность
              0

              Да если бы только в винде дело было (там хоть PowerShell теперь есть). Мы, например, у себя Apache Livy подняли, так там послать в Python (причём в третий, где таких проблем, по идее, быть не должно) что-то не-ASCII невозможно, приходится все строки кодировать через escape-последовательности.

              0

              Вот бы ещё такой же подробный разбор про utf8mb4

                +1
                Я постараюсь, но не обещаю)
                0
                Тема нормализации не раскрыта :)
                  +1
                  Ещё было бы неплохо упомянуть о существовании UTF-16LE / UTF-16BE, а также упомянуть, что UTF-8 всегда кодируется единообразно, несмотря на порядок байт хост системы, в чём несомненный плюс этой кодировки по сравнению с UTF-16.
                    +1
                    Да было бы конечно неплохо, но получилась бы очень длинная статья, как по мне, нужно было бы тогда написать про big endian, little endian, от чего это зависит, чем отличается.
                    А хотелось максимально подробно самую суть описать.
                    Если вдруг будет продолжение то непременно)
                    0
                    А я вот не вижу смысла в юникоде в командной строке. Ладно, в pdf или иксовых приложениях — там нужно бывает всякие разные символы отображать, не входящие в КОИ8-Р, но в консоли за глаза хватает восьмибитной кодировки. Да еще и дополнительный бонус: в MAXPATH можно вместить больше символов!
                      0
                      Ну отобразите мне файлы с иероглифами в именах.
                        –2
                        Зачем? Вы понимаете китайский? Ну, если так, то вам пригодится юникод.
                        Мне же это не нужно!
                          0
                          И что теперь, ради вас делать отдельную консоль?
                            –1
                            Зачем? У меня КОИ8-Р и меня это превосходно устраивает!
                            0
                            Нет, накачал японской музыки.
                              –3
                              Поделиться скриптом для переименования файлов (задает имена вида 0001.suff, 0002.suff и т.д.)?
                                0
                                Зачем мне увеличивать энтропию вселенной? У меня юникодная консоль, и эмулятор терминала и FS и GUI.
                        +1
                        Хорошая статья, но самое сложное в современных текстах осталось за скобками:
                        графемы, направленность текста, эмодзи и модификаторы (типа цвета кожи).

                          +3

                          Конечно хорошая, поэтому я немного поправлю ваш комментарий:
                          "..., но ХОТЕЛОСЬ бы узнать про самое сложное в современных текстах: графемы, направленность текста, эмодзи и модификаторы".

                            +1
                            Приму к сведению, хорошая тема
                            0
                            байта (будьте внимательны, если будете переводить символы в двоичную систему с помощью например онлайн конвертера, то первый нулевой ведущий байт может быть отброшен, что может сбить с толку).

                            Правильнее бит? Почему-то через ctrl+enter не отправить.
                              0
                              Все верно, спасибо
                              +1
                              если ведущий (первый) бит нулевой

                              01100101 — первый бит ноль, значит 1 байт кодирует 1 символ -> «e»

                              Тут надо быть поаккуратнее.
                              При рассмотрении байта традиционно крайний правый бит считают нулевым, а крайний левый — седьмым.
                              Автор же вводит понятие «ведущий», да еще и указывает «первый» бит, нарушая общепринятые нормы. В приведенном им примере
                              01100101
                              первый бит (если следовать устоявшимся традициям) — это второй справа: 01100101 — я его выделил жирным цветом и подчеркнул.
                              Далее автор приводит примеры, поясняющие его же слова, и в целом понятно о чем идет речь, но лучше уж следовать общепринятой методологии.
                              Спасибо автору за статью.
                                0
                                Спасибо, все верно, упустил.
                                Скорректирую текст в соответствии с нормами
                                0
                                fm-00, Извините, может у Вас есть идея как двоично безопасно перевести байты 128..255
                                в utf-8, чтобы потом можно их восстановить не указывая исходную кодировку?

                                Дано двоичный поток байтов от 0 до 255. Надо его конвертировать в UTF-8 и обратно.
                                \u0-u7f не искажаются, а вот в диапазоне \u80 (& # 128)-\uff (& # 255)
                                есть Диакрити́ческие зна́ки, которые в разных кодировках потом восстанавливаются по разному :(
                                  0

                                  Традиционно: блоб кодируется в base64, получаемая base64-строка в уже в ASCII и совместима с другими кодировками. Например, [0x69, 0x73, 0x20, 0xDE, 0xAD] => "aXMg3q0=". Преимущества: стандартизированный алгоритм. Недостатки: ASCII-байты не видно и результат всегда занимает на треть больше места.


                                  Вообще можете просто закодировать байты как Unicode-символы в UTF-8, оставляя ASCII-символы как есть, а у остальных экранируя два старших бита. Например, 0xDE => [0xC0 + 0xDE >> 6, 0x80 + 0xDE & 0x3F] = [0xC3, 0x9E]. Результат является корректным UTF-8 текстом, так как в диапазоне U+0080 — U+00FF нет комбинирующихся символов и прочих особенностей.


                                  А стоп… проблема, похоже, как раз в том, что полученный текст страдает потом от «умных» нормализаторов (потому что декомбинирующиеся символы в том диапазоне есть). Ну тогда можно кодировать старший бит каким-нибудь UTF-8 символом: 0xDE => [0xC2, 0x80, 0xDE & 0x7F] = [0xC2, 0x80, 0x5E]. То есть сбросить старший бит (опустив до ASCII) и приписать спереди UTF-8 байты для U+0080 Padding Character, который наверное никто не тронет.

                                    0
                                    Надежда была, что я не знал, про какую-то управляющую структуру UTF, типа дальше идет двоичный объект из стольких-то байтов.

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

                                    За прошлый год несколько раз полностью
                                    рассыпался документ в openOffice. Копируешь в него, сохранение, открываешь
                                    файл через некоторое время, и весь текст из непонятной мешанины символов.
                                    В принципе знаешь, что это мог быть сбойный байт или бит оказаться на винте, или при сохранение/чтение ошибка какая в программе из-за всех этих наворотов.

                                      0
                                      Надежда была, что я не знал, про какую-то управляющую структуру UTF, типа дальше идет двоичный объект из стольких-то байтов.

                                      Да это была бы хорошая штука, особенно если бы еще и не особо влияла на конечный вес файла, но к сожалению не зная исходной кодировки нет универсального способа, чтобы однозначно ее определить
                                  –1
                                  Чтобы получить детальное понимание этого вопроса придется прочитать и свести воедино не одну статью и потратить довольно значительное время на это.
                                  Для детального понимания вопроса наверно будет достаточно всего одной статьи: Краткая история систем кодирования символов естественных языков в США, Европе и Восточно-азиатских странах

                                  А посмотреть на проблему кодировок с точки зрения глобальной политики можно тут: «Проблема кодировок»: стечение обстоятельств или стратегический замысел?
                                    0
                                    В свое время почему-то безнадежно путался в терминологии.
                                    И все же:
                                    ascii — и таблица и кодировка (или просто кодировки как таковой просто нет)?
                                    кодировка и кодовая страница — синонимы?
                                      0
                                      ascii — и таблица и кодировка (или просто кодировки как таковой просто нет)?

                                      тут вы очень хорошо описали чем является ascii это таблица и кодировка (но по факту кодировки нет)

                                      кодировка и кодовая страница — синонимы?

                                      возможно это холиварный вопрос, но все же это не синонимы ну или не всегда это синонимы
                                        0
                                        ASCII — Американский стандарт… только для 7 бит. Фактически все остальные однобайтовые
                                        кодировки с ним совместимы. Но следует отметить, что все же есть вариации 14 символов
                                        (национальные) 23,24,25,2A,40,5B,5C,5D,5E,60,7B,7C,7E
                                        Из-за совместимости все кодовые страницы базировались на ascii
                                        0
                                        Детали появления UTF-16 жалко не написали. Не понятно, зачем она вообще нужна, если есть UTF-8? Ведь UTF-8 меньше занимает объёма и тоже переменной длины.
                                          0
                                          Если уж смотреть на кодировку с точки зрения производительности, то если выбирать хрюникод, нужно остановиться на utf-32!!!
                                          +1
                                          Пожалуйста поправьте в строке «2. в результате первого пункта будет получено число не больше FFFF, занимающее до 20 бит»
                                          FFFF на FFFFF
                                            0
                                            Спасибо, исправил
                                            0
                                            На самом деле с кодировками всё не так уж сложно, и я бы рекомендовал прочитать статью Joel Spolsky, или вот эти статьи на хабре: раз и два. Если вкратце, тут не одна проблема, а как минимум две (если оставить в стороне всякие юникодные комбинации и смайлики):
                                            — соответствие элементов языка и управляющих конструкций числам
                                            — способ хранения этих чисел в памяти
                                            По сути, когда заданы два этих отображения, мы уже можем интерпретировать байты в памяти машины как какой-то текст в определенной кодировке. И слово «юникод» на самом деле по своей сути относится к первой из этих проблем, а «UTF-8» или «UTF-16» — ко второй. А дальше возникает проблема в том, что какой-нибудь древний файл представляет из себя поток байт без указания на то, каким именно способом осуществлялись эти два преобразования. Если прочитать файл, записанный в кодировке KOI8-R, в память и интерпретировать его через CP-1251, мы получим некий «текст» в виде очень странной последовательности русских букв. А если его интерпретировать через CP-1252, получатся «кракозябры», так как в этой странице на месте байт, соответствующих русским буквам находятся всякие буквы с закорючками (диакритическими знаками). При сохранении в юникоде все эти символы останутся «как есть», но станут занимать не один байт, а несколько. При попытке их прочитать в другой кодировке начнутся проблемы.
                                            Но самое печальное происходит, когда в кодировке, в которой сохраняется файл, отсутствует часть символов. В этом случае ничего не остаётся, как заменить их на какой-то «пустой» символ, и часть информации теряется.
                                              0
                                              Ну раз уж про UTF речь завели, надо было и BOM упомянуть.
                                                0
                                                Было два выхода, указывать для каждой страницы кодировки, либо создать одну общую для всех символов в мире таблицу символов. Победил второй вариант, так создали Unicode таблицу символов.

                                                К сожалению, до конца проблему необходимости указывать язык/кодировку Unicode не решил. Из-за того, что разработчики Unicode вначале пытались уложиться в 65536 символов, они стали экономить codepoint'ы, присваивая один и тот же codepoint «похожим» иероглифам в разных языках. В итоге в лимит 65536 все равно не уложились, но при этом породили проблему Han unification. Поэтому, чтобы японский текст на Web-странице не выглядел у части пользователей «по-китайски», придется указывать тег 'lang=«ja»'. А для смешанных текстов (например, японско-китайский словарь) Unicode совсем не подходит, придется использовать другую кодировку (ISO2022, TRON и т.п.).

                                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                Самое читаемое