Как сделать юникод

Добавил пользователь Владимир З.
Обновлено: 18.09.2024

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

Печать вручную

Сайт MSDN утверждает, что вариантов для ручного ввода символа по коду есть три:

Alt+Numpad: A method of entering characters by typing in the character’s decimal code with the Numeric Pad keys (Num Lock turned on). In Windows:
* Alt+ , where xxx is the decimal value of a code point, generates an OEM-encoded character.
* Alt+ , where xxx is the decimal value of a code point, generates a Windows-encoded character.
* Alt+ + , where xxxx is the hexadecimal Unicode code point, generates a Unicode-encoded (UTF-16) character.

То бишь, можно вводить в OEM-кодировке (DOS), в Windows-кодировке, и в Unicode. В первых случаях код вводится в десятичной записи, во втором к нему слева приписывается 0. Оба варианта работают, а вот третий почему-то работать не захотел. Пришлось искать дальше, и вот решение - третий (шестнадцатеричный) способ ввода нужно активировать, и он работает не везде.
Активируется Unicode-ввод записью в реестре с последующей перезагрузкой, вот .reg-файл:

Затем открываем блокнот (у меня в нем работало, в броузерах - нет, выскакивало в адресную строку), зажимаем Alt и на цифровой клавиатуре, и вводим шестнадцатеричный Unicode-код символа. Неудобно до чертиков, да. Получаем квадратик, который можно скопировать в браузер и получить там нужный символ.

Кодировка текста – это схема нумерации символов, в которой каждому символу, цифре или знаку присвоено соответствующее число. Кодировку используют для сохранения и обработки текста на компьютере. Каждый раз при сохранении текста в файл он сохраняется с использованием определенной схемы кодирования, и при открытии этого файла необходимо использовать такую же схему, иначе восстановить исходный текст не получится. Самыми популярными кодировками для кириллицы сейчас являются UTF-8, Windows-1251 (CP1251, ANSI).

Для того чтобы программа смогла правильно открыть текстовый файл, иногда приходится вручную менять кодировку, перекодируя текст из одной схемы в другую. Например, не редко возникают проблемы с открытием файлов CSV, XML, SQL, TXT, PHP.

В этой небольшой статье мы расскажем о том, как изменить кодировку текстового файла на UTF-8, Windows-1251 или любую другую.

Блокнот Windows

меню Файл – Сохранить как

изменить кодировку в Блокноте

К сожалению, для подобных задач программа Блокнот часто не подходит. С ее помощью нельзя открывать документы большого размера, и она не поддерживает многие кодировки. Например, с помощью Блокнота нельзя открыть текстовые файлы в DOS 866.

Notepad++

Notepad++ (скачать) является одним из наиболее продвинутых текстовых редакторов. Он обладает подсветкой синтаксиса языков программирования, позволяет выполнять поиск и замену по регулярным выражениям, отслеживать изменения в файлах, записывать и воспроизводить макросы, считать хеш-сумы и многое другое. Одной из основных функций Notepad++ является поддержка большого количества кодировок текста и возможность изменения кодировки текстового файла в UTF-8 или Windows 1251.

выбрать кодировку в Notepad++

изменить кодировку в Notepad++

Akelpad

Akelpad (скачать) – достаточно старая программа для работы с текстовыми файлами, которая все еще актуальна и может быть полезной. Фактически Akelpad является более продвинутой версией стандартной программы Блокнот из Windows. С его помощью можно открывать текстовые файлы большого размера, которые не открываются в Блокноте, выполнять поиск и замену с использованием регулярных выражений и менять кодировку текста.

открыть файл в Akelpad

выбрать кодировку в Akelpad

изменить кодировку в Akelpad

В отличие от Notepad++, текстовый редактор Akelpad позволяет сохранить файл в практически любой кодировке. В частности, доступны Windows 1251, DOS 886, UTF-8 и многие другие.

В этом HOWTO обсуждается поддержка Python спецификации Юникод для представления текстовых данных и объясняются различные проблемы, с которыми люди обычно сталкиваются при работе с Юникод.

Знакомство с Юникодом¶

Определения¶

Стандарт Юникод описывает, как символы представлены кодовыми точками. Значение кодовой точки — это целое число в диапазоне от 0 до 0x10FFFF (около 1.1 миллиона значений, из которых на данный момент присвоено около 110 тысяч). В стандарте и в этом документе кодовая точка записывается с использованием обозначения U+265E для обозначения символа со значением 0x265e (9822 в десятичной системе).

Стандарт Юникод содержит множество таблиц, в которых перечислены символы и соответствующие им кодовые точки:

Символ представлен на экране или на бумаге набором графических элементов, который называется глифом. Например, глиф для прописной буквы A представляет собой два диагональных штриха и горизонтальный штрих, хотя точные детали будут зависеть от используемого шрифта. Большинству кода Python не нужно беспокоиться о глифах; определение правильного глифа для отображения, как правило, является задачей инструментария графического интерфейса пользователя или средства визуализации шрифтов терминала.

Кодировки¶

Это простое представление, но при его использовании возникает ряд проблем.

  1. Непереносимая; разные процессоры по-разному упорядочивают байты.
  2. Она занимает очень много места. В большинстве текстов большинство кодовых точек меньше 127 или меньше 255, поэтому много места занимают байты 0x00 . Вышеупомянутая строка занимает 24 байта по сравнению с 6 байтами, необходимыми для представления ASCII. Повышенное использование ОЗУ не имеет большого значения (настольные компьютеры имеют гигабайты ОЗУ, а строки обычно не такие большие), но увеличение использования диска и пропускной способности сети в 4 раза недопустимо.
  3. Она несовместима с существующими функциями C, такими как strlen() , поэтому необходимо использовать новое семейство широких строковых функций.

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

  1. Если кодовая точка = 128, она превращается в последовательность из двух, трёх или четырёх байтов, где каждый байт последовательности находится между 128 и 255.

У UTF-8 есть несколько удобных свойств:

Ссылки¶

Сайт Консорциума Юникода содержит символьные таблицы, глоссарий и PDF-версии спецификации. Будьте готовы к трудному чтению. Хронология происхождения и развития Юникод также доступен на сайте.

На канале Computerphile Youtube Том Скотт кратко обсуждает историю Юникод и UTF-8 (9 минут 36 секунд).

Чтобы помочь понять стандарт, Юкка Корпела написал вводное руководство для чтения таблиц символов Юникод.

Другая хорошая вступительная статья написал Джоэл Спольски. Если это введение не прояснило вам ситуацию, вам следует попробовать прочитать альтернативную статью, прежде чем продолжить.

Поддержка Юникода в Python¶

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

Строковый тип¶

Начиная с Python 3.0, тип языка str содержит символы Юникод, что означает любую строку, созданную с использованием "unicode rocks!" , 'unicode rocks!' или сохраняется строковый синтаксис с тройными кавычками как Юникод.

Кодировка по умолчанию для исходного кода Python — UTF-8, поэтому вы можете просто включить символ Юникод в строковый литерал:

Примечание: Python 3 также разрешает использование символов Юникод в идентификаторах:

Если вы не можете ввести определенный символ в своём редакторе или по какой-то причине хотите сохранить исходный код только в формате ASCII, вы также можете использовать escape-последовательности в строковых литералах. (В зависимости от вашей системы вы можете увидеть фактический глиф с заглавными буквами вместо экранирующего символа u.):

Кроме того, можно создать строку, используя метод decode() из bytes . Метод принимает аргумент encoding, например UTF-8, и, необязательно, аргумент errors.

Аргумент errors указывает ответ, когда входная строка не может быть преобразована в соответствии с правилами кодирования. Допустимые значения этого аргумента: 'strict' (вызвать исключение UnicodeDecodeError ), 'replace' (использовать U+FFFD , СИМВОЛ ЗАМЕНЫ ), 'ignore' (просто исключить символ из результата Юникод) или 'backslashreplace' (вставить escape-последовательность \xNN ). Следующие примеры показывают различия:

Кодировки задаются как строки, содержащие имя кодировки. У Python около 100 различных кодировок; см. список в справочнике по библиотеке Python в стандартные кодировки . Некоторые кодировки имеют несколько имён; например: 'latin-1' , 'iso_8859_1' и '8859 — все синонимы для одной и той же кодировки.

Односимвольные Юникод строки также могут быть созданы с помощью встроенной функции chr() , которая принимает целые числа и возвращает Юникод строку длиной 1, содержащую соответствующую кодовую точку. Обратной операцией является встроенная функция ord() , которая принимает односимвольную строку Юникод и возвращает значение кодовой точки:

Преобразование в байты¶

Метод, противоположный bytes.decode() — str.encode() , который возвращает bytes представление строки Юникод, закодированной в запрошенной кодировке.

Параметр errors такой же, как параметр метода decode() , но поддерживает ещё несколько возможных обработчиков. Помимо 'strict' , 'ignore' и 'replace' (который в данном случае вставляет вопросительный знак вместо некодируемого символа), существует также 'xmlcharrefreplace' (вставляет ссылку на символ XML), backslashreplace (вставляет escape- последовательность \uNNNN ) и namereplace (вставляет escape- последовательность) \N<. >` escape-последовательность).

В следующем примере показаны разные результаты:

Подпрограммы низкого уровня для регистрации и доступа к доступным кодировкам находятся в модуле codecs . Реализация новых кодировок также требует понимания модуля codecs . Однако функции кодирования и декодирования, возвращаемые этим модулем, обычно более низкоуровневые, чем это удобно, а написание новых кодировок — это специализированная задача, поэтому модуль не будет рассматриваться в этом HOWTO.

Литералы Юникода в исходном коде Python¶

В исходном коде Python определенные кодовые точки Юникод могут быть записаны с использованием escape-последовательности \u , за которой следуют четыре шестнадцатеричные цифры, дающие кодовую точку. Управляющая последовательность \U аналогична, но предполагает восемь шестнадцатеричных цифр, а не четыре:

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

Python по умолчанию поддерживает написание исходного кода в UTF-8, но вы можете использовать практически любую кодировку, если объявите используемую кодировку. Это делается путём включения специального комментария в первой или второй строке исходного файла:

Если вы не добавите такой комментарий, по умолчанию будет использоваться кодировка UTF-8, как уже упоминалось. См. также PEP 263 для получения дополнительной информации.

Свойства Юникода¶

Спецификация Юникод включает базу данных с информацией о кодовых точках. Для каждой определенной кодовой точки информация включает имя символа, его категорию, числовое значение, если применимо (для символов, представляющих числовые понятия, такие как римские цифры, дроби, такие как одна треть и четыре пятых и т. д.). Есть также свойства, связанные с отображением, например, как использовать кодовую точку в двунаправленном тексте.

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

При запуске печатает:

Сравнение строк¶

Вторым инструментом является функция normalize() модуля unicodedata , которая преобразует строки в одну из нескольких нормальных форм, где буквы, за которыми следует объединяющий символ, заменяются одиночными символами. normalize() можно использовать для выполнения сравнений строк, которые не будут ложно сообщать о неравенстве, если две строки по-разному используют комбинирующие символы:

При запуске выводит:

Первым аргументом функции normalize() является строка, дающая желаемую форму нормализации, которая может быть одной из NFC, NFKC, NFD и NFKD.

Стандарт Юникод также определяет, как проводить сравнения без регистра:

(Почему NFD() вызывается дважды? Поскольку есть несколько символов, которые заставляют casefold() возвращать ненормализованную строку, поэтому результат необходимо снова нормализовать. См. обсуждение и пример в разделе 3.13 стандарта Юникод.)

Регулярные выражения Юникод¶

Регулярные выражения, поддерживаемые модулем re , могут быть представлены в виде байтов или строк. Некоторые последовательности специальных символов, такие как \d и \w , имеют разные значения в зависимости от того, предоставляется ли шаблон в виде байтов или строки. Например, \d будет соответствовать категории символов 3 в байтах, но в строках будет соответствовать любому символу, который находится в 'Nd' категории.

Строка в этом примере будет числом 57, записанное как тайскими, так и арабскими цифрами:

Аналогично, \w соответствует большому количеству символов Юникод, но только в байтах [a-zA-Z0-9_] или, если указан re.ASCII , а \s будет соответствовать либо пробельным символам Юникод, либо [ \t\n\r\f\v] .

Ссылки¶

Есть несколько хороших альтернативных обсуждений поддержки Юникод в Python:

    , Ника Коглана. , презентация Неда Батчелдера на PyCon 2012.

Тип str описан в справочнике по библиотеке Python по адресу .

Документация к модулю unicodedata .

Документация к модулю codecs .

Чтение и запись данных Юникод¶

Как только вы написали код, который работает с данными Юникод, следующая проблема — ввод/вывод. Как включить строки Юникод в свою программу и как преобразовать Юникод в форму, подходящую для хранения или передачи?

Возможно, вам не потребуется ничего делать в зависимости от ваших источников ввода и назначения вывода; вы должны проверить, поддерживают ли библиотеки, используемые в вашем приложении, Юникод изначально. Например, синтаксические анализаторы XML часто возвращают данные Юникод. Многие реляционные базы данных также поддерживают столбцы со значениями Юникод и могут возвращать значения Юникод из запроса SQL.

Одной из проблем является многобайтовый характер кодировок; один символ Юникод может быть представлен несколькими байтами. Если вы хотите читать файл фрагментами произвольного размера (скажем, 1024 или 4096 байтов), вам необходимо написать код обработки ошибок, чтобы уловить случай, когда только часть байтов, кодирующих один символ Юникод, читается в конце кусока. Одним из решений может быть считывание всего файла в память, а затем выполнение декодирования, но это мешает вам работать с файлами очень большого размера; если вам нужно прочитать файл размером 2 ГиБ, вам потребуется 2 ГиБ ОЗУ. (Более того, поскольку, по крайней мере, на мгновение вам понадобятся как закодированная строка, так и её версия Юникод в памяти.)

Решением будет использование низкоуровневого интерфейса декодирования, чтобы уловить случай частичных последовательностей кодирования. Работа по реализации этого уже была сделана за вас: встроенная функция open() может возвращать файловый объект, который предполагает, что содержимое файла находится в указанной кодировке, и принимает параметры Юникод для таких методов, как read() и write() . Это работает через параметры encoding и errors open() , которые интерпретируются так же, как в str.encode() и bytes.decode() .

Поэтому читать Юникод из файла очень просто:

Также можно открывать файлы в режиме обновления, позволяя читать и писать:

Имена файлов в Юникоде¶

Большинство широко используемых сегодня операционных систем поддерживают имена файлов, содержащие произвольные символы Юникод. Обычно это реализуется путём преобразования строки Юникод в некоторую кодировку, которая зависит от системы. Сегодня Python все больше и больше использует UTF-8: Python в MacOS использовал UTF-8 для нескольких версий, а Python 3.6 также перешёл на использование UTF-8 в Windows. В системах Unix кодировка файловой системы будет только в том случае, если вы установили переменные среды LANG или LC_CTYPE ; если нет, кодировка по умолчанию снова UTF-8.

Функция sys.getfilesystemencoding() возвращает кодировку для использования в вашей текущей системе, если вы хотите выполнить кодирование вручную, но нет особых причин для беспокойства. При открытии файла для чтения или записи вы обычно можете просто указать строку Юникод в качестве имени файла, и она будет автоматически преобразована в нужную для вас кодировку:

Функции модуля os , такие как os.stat() , также принимают имена файлов Юникод.

Функция os.listdir() возвращает имена файлов, что вызывает вопрос: должна ли она возвращать версию имен файлов в формате Юникод или должна возвращать байты, содержащие закодированные версии? os.listdir() может делать и то, и другое, в зависимости от того, предоставили ли вы путь к каталогу в байтах или в строке Юникод. Если вы передадите строку Юникод в качестве пути, имена файлов будут декодированы с использованием кодировки файловой системы, и будет возвращен список строк Юникод, а передача байтового пути вернёт имена файлов в байтах. Например, предполагая, что кодировка файловой системы по умолчанию — UTF-8, запустите следующую программу:

вернёт следующий результат:

Первый список содержит имена файлов в кодировке UTF-8, а второй список содержит версии Юникод.

Обратите внимание, что в большинстве случаев вы можете просто использовать Юникод с этими API. API байтов следует использовать только в системах, где могут присутствовать недекодируемые имена файлов; сейчас это в основном только системы Unix.

Советы по написанию программ с поддержкой Юникод¶

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

Самый важный совет:

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

Если вы попытаетесь написать функции обработки, которые принимают как Юникод, так и байтовые строки, вы обнаружите, что ваша программа уязвима для ошибок везде, где вы комбинируете два разных типа строк. Нет автоматического кодирования или декодирования: если вы это сделаете, например, str + bytes , будет поднято TypeError .

При использовании данных, поступающих из веб-браузера или другого ненадежного источника, распространенным методом является проверка на недопустимые символы в строке перед использованием строки в сгенерированной командной строке или сохранением её в базе данных. Если вы делаете это, будьте осторожны и проверяйте декодированную строку, а не закодированные байтовые данные; некоторые кодировки могут иметь интересные свойства, например, не быть биективными или не быть полностью совместимыми с ASCII. Это особенно верно, если во входных данных также указана кодировка, поскольку злоумышленник может выбрать хитрый способ скрыть вредоносный текст в закодированном байтовом потоке.

Преобразование между кодировками файлов¶

Класс StreamRecoder может прозрачно преобразовывать между кодировками, принимая поток, который возвращает данные в кодировке №1, и ведёт себя как поток, возвращающий данные в кодировке №2.

Например, если у вас есть входной файл f в Latin-1, вы можете обернуть его StreamRecoder , чтобы вернуть байты в кодировке UTF-8:

Файлы в неизвестной кодировке¶

Что делать, если вам нужно внести изменения в файл, но вы не знаете его кодировку? Если вы знаете, что кодировка совместима с ASCII, и хотите проверить или изменить только части ASCII, вы можете открыть файл с помощью обработчика ошибок surrogateescape :

Обработчик ошибок surrogateescape декодирует любые байты, отличные от ASCII, как кодовые точки в специальном диапазоне от U+DC80 до U+DCFF. Затем эти кодовые точки снова превратятся в те же байты, когда обработчик ошибок surrogateescape используется для кодирования данных и их обратной записи.

Ссылки¶

Одна секция Освоение Ввода-Вывода Python 3, речь на PyCon 2010 Дэвидом Бизли, обсуждает текстовую обработку и обработку двоичных данных.

Сила Юникода в Python - это выступление Бенджамина Питерсона на PyCon 2013, в котором обсуждается внутреннее представление Юникода в Python 3.3.

Благодарности¶

Первоначальный черновик этого документа был написан Эндрю Кучлингом. С тех пор он был переработан Александром Белопольским, Георгом Брандлом, Эндрю Кучлингом и Эцио Мелотти.

Благодарим следующих людей, которые отметили ошибки или предложили предложения по этой статье: Эрик Араужо, Николас Бастин, Ник Коглан, Мариус Гедминас, Кент Джонсон, Кен Круглер, Марк-Андре Лембург, Мартин фон Лёвис, Терри дж. Риди, Сергей Сторчака, Эрик Сан, Чад Уитакр, Грэм Уайдман.


Возникают вопросы: что происходит, кто виноват? Ответ не будет коротким.

1. Компьютер – человек

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

2. ASCII

Так как первые вычислительные машины были малоемкими, для представления в их памяти всего набора требуемых знаков хватало 7 бит (или 128 символов). Сюда входил весь английский алфавит в верхнем и нижнем регистрах, цифры, знаки, вспомогательные символы.

С другими свойствами модуля можете ознакомиться самостоятельно.

Потребовалось указание кодировок в заголовках документов.

3. Юникод-стандарт


Photo by Tomas Martinez on Unsplash

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

Я расскажу краткую историю кодировки символов (и о том, сколь мало она была стандартизирована), а затем чуть подробнее остановлюсь на том, чем мы пользуемся в настоящее время.

Введение в кодирование символов

Компьютер понимает только двоичный код. То есть только нули и единицы. Каждая из этих цифр — один бит. Восемь таких цифр (нулей и/или единиц) — один байт.

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

Но если весь текст, который вы читаете, тоже был в форме нулей и единиц, то как же произошло его превращение в понятные человеку слова? Чтобы в этом разобраться, давайте вернемся к истокам.

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

На заре интернета в нем все было исключительно на английском. Нам не приходилось беспокоиться о символах, которых в английском языке просто нет. Для сопоставления всех нужных символов с числовыми кодами использовалась таблица ASCII (American standard code for information interchange).

Получаемый компьютером двоичный код:

Одного байта (8 бит) вполне хватало, чтобы уникально закодировать любой символ английского языка, а также некоторое количество управляющих символов. Часть этих управляющих символов использовалась для телетайпов, которые были довольно распространены в то время. Сейчас, впрочем, не используются ни телетайпы, ни эти символы.

Что из себя представляют управляющие символы? Например, управляющий символ с кодом 7 (111 в двоичной системе) служит для подачи компьютером звукового сигнала. Символ с кодом 8 (1000 в двоичной системе) перемещает позицию печати на один символ назад (например, для наложения одного символа на другой или для стирания предшествующего символа). Символ с кодом 12 (1100 в двоичной системе) отвечает за очистку экрана терминала.

В то время компьютеры использовали 8 бит для одного байта (хотя так было не всегда), так что проблем не было. Это позволяло закодировать все управляющие символы, все цифры и буквы английского алфавита, да еще и свободные коды оставались! Дело в том, что 1 байт может принимать 256 (0 — 255) разных значений. То есть потенциально можно было закодировать 255 символов, а в ASCII их было всего 127. Так что 128 кодов оставались неиспользованными.

Давайте посмотрим на саму таблицу ASCII. Все символы алфавита в верхнем и нижнем регистре, а также цифры получили двоичные коды. Первые 32 символа таблицы — управляющие, они не имеют графического отображения.

Таблица ASCII

Как видите, символы кончаются кодом 127. У нас осталось свободное место в таблице.

Проблемы с ASCII

Американский институт национальных стандартов (American national standards institute, ANSI) разметил, за какие символы должны отвечать коды 0-127 (т. е., те, которые уже были размечены ASCII). Но остальные коды остались открытыми.

Примечание: не путайте ANSI (институт) и ASCII (таблица).

Назначение кодов 0-127 никто не оспаривал. Проблема была в том, что делать с оставшимися.

Но в других компьютерах было по-другому. И буквально каждый производитель стремился по-своему применить свободные коды из конца таблицы ASCII.

Эти разные варианты концовок таблицы ASCII назывались кодовыми страницами.

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

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

Но как же, черт побери, все это стандартизировать? Как работать с несколькими языками? А с одним языком, но разными кодовыми страницами? А с не-английским языком?

В китайском языке больше 100 тысяч различных символов. Даже если бы мы договорились отдать под символы китайского языка все оставшиеся коды, их бы все равно не хватило.

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


Пример mojibake

С ума сойти…

Вот именно! У нас не было ни единого шанса надежно обмениваться данными.

Интернет — всего лишь огромная сеть компьютеров по всему миру. Представьте, что было бы, если бы каждая страна самостоятельно определяла стандарты кодировки. Тогда компьютеры в Греции нормально выводили бы только греческий язык, а в США — только английский.

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

���Если только вам������, конечно, не ���нравится ��� расшифровывать такие абзацы.�֎֏0590֐��׀ׁׂ׃ׅׄ׆ׇ

И тут пришел Юникод

Юникод (Unicode) иногда называют UCS — универсальным набором символов (Universal Coded Character Set), и даже ISO/IEC 10646. Но Юникод — наиболее распространенное название.

Юникод состоит из множества кодовых пунктов (code points, по сути — шестнадцатеричные числа), связанных с символами. Коллекция кодовых пунктов называется набором символов. Вот этот набор — и есть Юникод.

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

U+ указывает на то, что это стандарт Unicode, а номер — число, в которое переведен двоичный код для данного символа. В Юникоде используется шестнадцатеричная система — просто потому, что в нее проще переводить двоичный код. Впрочем, вам не придется делать это вручную, так что можно не волноваться.

Вот ссылка на ресурс, где вы можете впечатать в форму любой символ и получить его кодировку в Юникод. Или же можете просмотреть все 143859 символов здесь. В таблице можно увидеть, из какой части света происходит каждый символ!

Просто для ясности подобью итоги. В настоящее время у нас есть большой словарь кодовых пунктов с отображением на символы. Это очень большое множество символов. Н

Наконец, переходим к последнему ингредиенту.

Unicode Transform Format (UTF)

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

Поскольку кодировок так много, как понять, какую использовать? Есть такая вещь как маркер последовательности байтов (англ. Byte order mark, BOM) Это двубайтный маркер в начале файла, который говорит о том, какая кодировка используется в этом файле.

UTF-8 — самая распространенная кодировка в интернете. В HTML5 она определена как предпочтительная для новых документов. Поэтому я уделю ей особое внимание.


Даже по диаграмме 2012 года видно, что UTF-8 становится самой распространенной кодировкой.


Диаграмма от W3 показывает, насколько интенсивно используется UTF-8 на сайтах

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

UTF-8 кодирует кодовые пункты Юникод 0-127 в одном байте (т. е. так же, как в ASCII). Это значит, что если вы для своей программы использовали кодировку ASCII, а ваши пользователи используют UTF-8, они не заметят никакой разницы. Все будет нормально работать.

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

В названии кодировки заложено указание на количество бит (8 бит = 1 байт), которые используются для одного кодового пункта. Но есть символы Юникод, для хранения которых требуется по нескольку байтов (раньше было до 6, теперь — до 4, в зависимости от символа). Именно это имеется в виду, когда говорят, что UTF-8 — кодировка переменной длины (см. UTF-32, — прим. ред.).

Тут все зависит от языка. Символ английского алфавита — 1 байт. Европейская латиница, иврит, арабские символы представляются 2 байтами. Для китайских, японских, корейских символов и символов других азиатских языков используются 3 байта.

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

Радостно сознавать, что теперь у нас полное согласие по части того, как кодировать шумерскую клинопись, а также смайлики!

Если описать весь процесс в общих чертах, то:

  1. сначала вы читаете BOM, чтобы узнать кодировку,
  2. затем расшифровываете файл в кодовые пункты Юникод,
  3. затем представляете символы из набора Юникод в символы, которые отрисовываются на экране.

Еще немного о UTF

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

Как мы указываем кодировку? Поскольку HTML написан на английском и практически все кодировки прекрасно справляются с английскими символами, мы можем указать кодировку прямо сверху, в разделе .

Это важно сделать в самом начале , потому что если будет использована не та кодировка, парсинг HTML может начаться заново.

Это все?

Работа над Юникодом продолжается. Как в любом стандарте, мы можем что-то добавлять, удалять, вносить предложения. Никакая спецификация никогда не считается окончательно завершенной.

Обычно бывает 1-2 релиза Юникода в год, найти их можно здесь.

Недавно мне попалась статья об очень интересном баге: Twitter неверно рендерил русские символы Юникода.

Если вы дочитали до сюда, — снимаю шляпу. Я знаю, информации много.

Посмотрите, как могут ломаться сайты из-за неправильной кодировки. Я использовал вот это расширение Google Chrome для смены кодировки и пробовал читать разные страницы. Текст был совершенно непонятен. Попробуйте прочесть эту статью, например. Зайдите на Википедию. Посмотрите на Mojibake своими глазами.

Это поможет вам проникнуться важностью кодировок.

Окно выбора кодировки

Заключение

Название этой статьи — дань уважения статье Джоела Спольски, которая познакомила меня с кодировкой и многими концепциями, о которых я и не подозревал. Именно после прочтения этой статьи я углубился в тему кодировки. Также я очень многое почерпнул из этого источника.

Изучая информацию и пытаясь упростить свою статью, я узнал о Майкле Эверсоне. С 1993 года он предложил больше 200 изменений в Юникод и добавил в стандарт тысячи символов. В 2003 году он был одним из ведущих контрибьюторов предложений в Юникод. Своим современным видом Юникод (а значит, и вообще интернет) во многом обязан именно Майклу Эверсону.

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

Читайте также: