java символ по коду unicode
Очень странные вещи c Java Characters
Тайна ошибки комментария и другие истории.
Вступление
Знаете ли вы, что следующее является допустимым выражением Java?
Вы можете попробовать скопировать и вставить его в основной метод любого класса и скомпилировать. Если вы затем добавите следующий оператор
и после компиляции запустите этот класс, код напечатает число 8!
А знаете ли вы, что этот комментарий вместо этого вызывает синтаксическую ошибку во время компиляции?
Тем не менее, комментарии не должны приводить к синтаксическим ошибкам. Фактически, программисты часто комментируют фрагменты кода, чтобы компилятор их игнорировал. так что же происходит?
Примитивный тип данных char
Как всем известно, char это один из восьми примитивных типов Java. Это позволяет нам хранить по одному символу. Ниже приведен простой пример, в котором значение символа присваивается типу char :
На самом деле этот тип данных используется нечасто, потому что в большинстве случаев программистам нужны последовательности символов и поэтому они предпочитают строки. Каждое буквальное значение символа должно быть заключено между двумя одинарными кавычками, чтобы не путать с двойными кавычками, используемыми для строковых литералов. Объявление строки:
используя один печатный символ на клавиатуре (например ‘&’ ).
используя специальный escape-символ (например, ‘\n’ который указывает символ перевода строки).
Давайте добавим некоторые детали в следующих трех разделах.
Печатаемые символы клавиатуры
Мы можем назначить любой символ, найденный на нашей клавиатуре, char переменной, при условии, что наши системные настройки поддерживают требуемый символ и что этот символ доступен для печати (например, клавиши «Canc» и «Enter» не печатаются).
Тип данных char хранится в 2 байтах (16 бит), а диапазон состоит только из положительных чисел от 0 до 65 535. Фактически, существует «отображение», которое связывает определенный символ с каждым числом. Это отображение (или кодирование) определяется стандартом Unicode (более подробно описанным в следующем разделе).
Формат Unicode (шестнадцатеричное представление)
Мы можем напрямую присвоить Unicode char значение в шестнадцатеричном формате, используя 4 цифры, которые однозначно идентифицируют данный символ, добавляя к нему префикс \u (всегда в нижнем регистре). Например:
В данном случае мы говорим о литерале в формате Unicode (или литерале в шестнадцатеричном формате). Фактически, при использовании 4 цифр в шестнадцатеричном формате охватывается ровно 65 536 символов.
Специальные escape-символы
В char типе также можно хранить специальные escape-символы, то есть последовательности символов, которые вызывают определенное поведение при печати:
\b эквивалентно backspace, отмене слева (эквивалентно клавише Delete).
\n эквивалентно переводу строки (эквивалентно клавише Ente).
\\ равняется только одному \ (только потому, что символ \ используется для escape-символов).
\t эквивалентно горизонтальной табуляции (эквивалентно клавише TAB).
\’ эквивалентно одинарной кавычке (одинарная кавычка ограничивает литерал символа).
\» эквивалентно двойной кавычке (двойная кавычка ограничивает литерал строки).
\r представляет собой возврат каретки (специальный символ, который перемещает курсор в начало строки).
\f представляет собой подачу страницы (неиспользуемый специальный символ, представляющий курсор, перемещающийся на следующую страницу документа).
Обратите внимание, что присвоение литерала ‘»‘ символу совершенно законно, поэтому следующий оператор:
что эквивалентно следующему коду:
правильно и напечатает символ двойной кавычки:
Если бы мы попытались не использовать escape-символ для одиночных кавычек, например, со следующим утверждением:
мы получим следующие ошибки времени компиляции, поскольку компилятор не сможет различить разделители символов:
Поскольку разделители строковых литералов представлены в двойных кавычках, ситуация обратная. Фактически, внутри строки можно заключить одинарные кавычки:
С другой стороны, мы должны использовать \» escape-символ, чтобы использовать двойные кавычки в строке. Итак, следующее утверждение:
вызовет следующие ошибки компиляции:
Вместо этого верна следующая инструкция:
Написание Java кода в формате Unicode
Литеральный формат Unicode также можно использовать для замены любой строки нашего кода. Фактически, компилятор сначала преобразует формат Unicode в символ, а затем оценивает синтаксис. Например, мы могли бы переписать следующий оператор:
Фактически, если мы добавим к предыдущей строке следующий оператор:
Несомненно, это бесполезный способ написания нашего кода. Но может быть полезно знать эту функцию, поскольку она позволяет нам понять некоторые ошибки, которые (редко) случаются.
Формат Unicode для escape-символов
мы получим следующую ошибку времени компиляции:
В реальности, компилятор преобразует предыдущий код в следующий перед его оценкой:
Формат Unicode был преобразован в символ новой строки, и предыдущий синтаксис не является допустимым синтаксисом для компилятора Java.
Также в этом случае компилятор преобразует предыдущий код следующим образом:
что приведет к следующим ошибкам времени компиляции:
Первая ошибка связана с тем, что первая пара кавычек не содержит символа, а вторая ошибка указывает на то, что указание третьей одинарной кавычки является незакрытым символьным литералом.
мы получим следующую ошибку времени компиляции:
Фактически, компилятор преобразовал число в формате Unicode в возврат каретки, вернув курсор в начало строки, и то, что должно было быть второй одинарной кавычкой, стало первой.
мы получим следующую ошибку времени компиляции:
Это потому, что предыдущий код будет преобразован в следующий:
и поэтому пара символов ‘ рассматривается как escape-символ, соответствующий одинарной кавычке, и поэтому в буквальном закрытии отсутствует другая одинарная кавычка.
проблем не будет. Но если мы используем этот символ внутри строки:
мы получим следующую ошибку времени компиляции:
поскольку предыдущий код будет преобразован в следующий:
Тайна ошибки комментария
Еще более странная ситуация возникает при использовании однострочных комментариев для форматов Unicode, таких как возврат каретки или перевод строки. Например, несмотря на то, что оба следующих оператора закомментированы, могут возникнуть ошибки во время компиляции!
Это связано с тем, что компилятор всегда преобразует шестнадцатеричные форматы с помощью символов перевода строки и возврата каретки, которые несовместимы с однострочными комментариями; они печатают символы вне комментария!
Чтобы разрешить ситуацию, используйте обозначение многострочного комментария, например:
Выводы
В этой статье мы увидели, что использование типа char в Java скрывает некоторые действительно удивительные особые случаи. В частности, мы увидели, что можно писать код Java, используя формат Unicode. Это связано с тем, что компилятор сначала преобразует формат Unicode в символ, а затем оценивает синтаксис. Это означает, что программисты могут находить синтаксические ошибки там, где они никогда не ожидали, особенно в комментариях.
Примечание автора: эта статья представляет собой короткий отрывок из раздела 3.3.5 «Примитивные символьные типы данных» тома 1 моей книги «Java для пришельцев». Для получения дополнительной информации посетите сайт книги (вы можете загрузить раздел 3.3.5 из области «Примеры»).
Таблица символов Юникода
Популярные наборы символов
Юникод
Юникод (по-английски Unicode) — это стандарт кодирования символов. Проще говоря, это таблица соответствия текстовых знаков (цифр, букв, элементов пунктуации ) двоичным кодам. Компьютер понимает только последовательность нулей и единиц. Чтобы он знал, что именно должен отобразить на экране, необходимо присвоить каждому символу свой уникальный номер. В восьмидесятых, знаки кодировали одним байтом, то есть восемью битами (каждый бит это 0 или 1). Таким образом получалось, что одна таблица (она же кодировка или набор) может вместить только 256 знаков. Этого может не хватить даже для одного языка. Поэтому, появилось много разных кодировок, путаница с которыми часто приводила к тому, что на экране вместо читаемого текста появлялись какие-то странные кракозябры. Требовался единый стандарт, которым и стал Юникод. Самая используемая кодировка — UTF-8 (Unicode Transformation Format) для изображения символа задействует от 1 до 4 байт.
Символы
Символы в таблицах Юникода пронумерованы шестнадцатеричными числами. Например, кириллическая заглавная буква М обозначена U+041C. Это значит, что она стоит на пересечении строки 041 и столбца С. Её можно просто скопировать и потом вставить куда-либо. Чтобы не рыться в многокилометровом списке следует воспользоваться поиском. Зайдя на страницу символа, вы увидите его номер в Юникоде и способ начертания в разных шрифтах. В строку поиска можно вбить и сам знак, даже если вместо него отрисовывается квадратик, хотя бы для того, чтобы узнать, что это было. Ещё, на этом сайте есть специальные (и не специальные — случайные) наборы однотипных значков, собранные из разных разделов, для удобства их использования.
Стандарт Юникод — международный. Он включает знаки почти всех письменностей мира. В том числе и тех, которые уже не применяются. Египетские иероглифы, германские руны, письменность майя, клинопись и алфавиты древних государств. Представлены и обозначения мер и весов, нотных грамот, математических понятий.
Сам консорциум Юникода не изобретает новых символов. В таблицы добавляются те значки, которые находят своё применение в обществе. Например, знак рубля активно использовался в течении шести лет прежде чем был добавлен в Юникод. Пиктограммы эмодзи (смайлики) тоже сначала получили широкое применение в Япониии прежде чем были включены в кодировку. А вот товарные знаки, и логотипы компаний не добавляются принципиально. Даже такие распространённые как яблоко Apple или флаг Windows. На сегодняшний день, в версии 8.0 закодировано около 120 тысяч символов.
© Таблица символов Юникода, 2012–2021.
Юникод® — это зарегистрированная торговая марка консорциума Юникод в США и других странах. Этот сайт никак не связан с консорциумом Юникод. Официальный сайт Юникода располагается по адресу www.unicode.org.
Мы используем 🍪cookie, чтобы сделать сайт максимально удобным для вас. Подробнее
Руководство по кодировке символов
Изучите кодировку символов в Java и узнайте о распространенных подводных камнях.
1. Обзор
В этом уроке мы обсудим основы кодирования символов и то, как мы справляемся с этим в Java.
2. Важность кодирования символов
Нам часто приходится иметь дело с текстами, принадлежащими к нескольким языкам с различными письменными знаками, такими как латинский или арабский. Каждый символ в каждом языке должен быть каким-то образом сопоставлен с набором единиц и нулей. Действительно, удивительно, что компьютеры могут правильно обрабатывать все наши языки.
Чтобы сделать это правильно, нам нужно подумать о кодировке символов. Невыполнение этого требования часто может привести к потере данных и даже уязвимостям безопасности.
Чтобы лучше понять это, давайте определим метод декодирования текста на Java:
Обратите внимание, что вводимый здесь текст использует кодировку платформы по умолчанию.
Ну, не совсем то, что мы ожидали.
Что могло пойти не так? Мы постараемся понять и исправить это в оставшейся части этого урока.
3. Основы
3.1. Кодирование
Например, первая буква в нашем сообщении, “T”, в US-ASCII кодирует в “01010100”.
3.2. Кодировки
3.3. Кодовый пункт
Кодовая точка-это абстракция, которая отделяет символ от его фактической кодировки. A кодовая точка – это целочисленная ссылка на определенный символ.
Мы можем представить само целое число в простых десятичных или альтернативных основаниях, таких как шестнадцатеричное или восьмеричное. Мы используем альтернативные базы для удобства ссылки на большие числа.
Например, первая буква в нашем сообщении, T, в Юникоде имеет кодовую точку “U+0054” (или 84 в десятичной системе счисления).
4. Понимание Схем Кодирования
Кодировка символов может принимать различные формы в зависимости от количества символов, которые она кодирует.
Количество закодированных символов имеет прямое отношение к длине каждого представления, которое обычно измеряется как количество байтов. Наличие большего количества символов для кодирования по существу означает необходимость более длинных двоичных представлений.
Давайте рассмотрим некоторые из популярных схем кодирования на практике сегодня.
4.1. Однобайтовое кодирование
Одна из самых ранних схем кодирования, называемая ASCII (Американский стандартный код для обмена информацией), использует однобайтовую схему кодирования. По сути, это означает, что каждый символ в ASCII представлен семибитными двоичными числами. Это все еще оставляет один бит свободным в каждом байте!
Ascii 128-символьный набор охватывает английские алфавиты в нижнем и верхнем регистрах, цифры и некоторые специальные и контрольные символы.
Давайте определим простой метод в Java для отображения двоичного представления символа в определенной схеме кодирования:
Теперь символ ” T ” имеет кодовую точку 84 в US-ASCII (ASCII в Java называется US-ASCII).
И если мы используем наш метод утилиты, мы можем увидеть его двоичное представление:
Это, как мы и ожидали, семиразрядное двоичное представление символа “T”.
Исходный ASCII оставил самый значимый бит каждого байта неиспользованным. В то же время ASCII оставил довольно много непредставленных символов,
Исходный ASCII оставил самый значимый бит каждого байта неиспользованным. || В то же время ASCII оставил довольно много непредставленных символов,
Было предложено и принято несколько вариантов схемы кодирования ASCII.
Многие расширения ASCII имели разные уровни успеха, но, очевидно, это
4.2. Многобайтовое кодирование
Поскольку потребность в размещении все большего количества символов росла, однобайтовые схемы кодирования, такие как ASCII, не были устойчивыми.
Это привело к появлению многобайтовых схем кодирования, которые имеют гораздо большую емкость, хотя и за счет увеличения требований к пространству.
Давайте теперь вызовем метод convertToBinary с вводом как “語”, китайский символ, и кодирование как “Big5”:
Вывод выше показывает, что кодировка Big5 использует два байта для представления символа “語”.
полный список кодировок символов, наряду с их псевдонимами, ведется Международным органом по номерам.
5. Юникод
Нетрудно понять, что, хотя кодирование важно, декодирование в равной степени жизненно важно для понимания представлений. Это возможно на практике только в том случае, если широко используется согласованная или совместимая схема кодирования.
Различные схемы кодирования, разработанные изолированно и практикуемые в местных географических регионах, начали становиться сложными.
Ну, для этого должно потребоваться несколько байтов для хранения каждого символа? Честно говоря, да, но у Unicode есть гениальное решение.
Unicode как стандарт определяет кодовые точки для каждого возможного символа в мире. Кодовая точка для символа “T” в Юникоде равна 84 в десятичной системе счисления. Обычно мы называем это “U+0054” в Юникоде, который представляет собой не что иное, как U+, за которым следует шестнадцатеричное число.
Мы используем шестнадцатеричную систему в качестве основы для кодовых точек в Юникоде, поскольку существует 1 114 112 точек, что является довольно большим числом для удобной передачи в десятичном формате!
То, как эти кодовые точки кодируются в биты, зависит от конкретных схем кодирования в Юникоде. Мы рассмотрим некоторые из этих схем кодирования в подразделах ниже.
5.1. UTF-32
Вывод выше показывает использование четырех байтов для представления символа “T”, где первые три байта-это просто потраченное впустую пространство.
5.2. UTF-8
Давайте снова вызовем метод convertToBinary с вводом как “T” и кодированием как ” UTF-8″:
Вывод в точности аналогичен ASCII, использующему только один байт. На самом деле UTF-8 полностью обратно совместим с ASCII.
Давайте снова вызовем метод convertToBinary с вводом как “語” и кодированием как ” UTF-8″:
Как мы видим здесь, UTF-8 использует три байта для представления символа “語”. Это известно как кодирование переменной ширины .
UTF-8, благодаря своей экономичности пространства, является наиболее распространенной кодировкой, используемой в Интернете.
6. Поддержка кодирования в Java
Есть некоторые тонкости в том, как Java подбирает кодировку для работы. Давайте рассмотрим их более подробно.
6.1. Кодировка по умолчанию
Это зависит от локали и кодировки базовой операционной системы, на которой работает JVM. Например, в macOS кодировка по умолчанию-UTF-8.
Давайте посмотрим, как мы можем определить кодировку по умолчанию:
Если мы запустим этот фрагмент кода на компьютере с Windows, то получим результат:
Теперь “windows-1252” – это кодировка по умолчанию платформы Windows на английском языке, которая в данном случае определила кодировку по умолчанию JVM, работающей в Windows.
6.2. Кто использует Кодировку по умолчанию?
Многие API Java используют кодировку по умолчанию, определенную JVM. Чтобы назвать несколько:
Итак, это означает, что если бы мы запустили наш пример без указания кодировки:
затем он будет использовать кодировку по умолчанию для ее декодирования.
И есть несколько API, которые делают этот же выбор по умолчанию.
Таким образом, кодировка по умолчанию приобретает важность, которую мы не можем безопасно игнорировать.
6.3. Проблемы С Набором Символов По Умолчанию
Как мы уже видели, кодировка по умолчанию в Java определяется динамически при запуске JVM. Это делает платформу менее надежной или подверженной ошибкам при использовании в разных операционных системах.
Например, если мы запустим
в macOS он будет использовать UTF-8.
Если мы попробуем тот же фрагмент кода в Windows, он будет использовать Windows-1252 для декодирования того же текста.
Или представьте, что вы пишете файл в mac OS, а затем читаете тот же файл в Windows.
Нетрудно понять, что из-за различных схем кодирования это может привести к потере или повреждению данных.
6.4. Можем ли мы переопределить кодировку по умолчанию?
Определение кодировки по умолчанию в Java приводит к двум системным свойствам:
Теперь интуитивно понятно переопределять эти системные свойства с помощью аргументов командной строки:
6.5. Почему Java Не Решает Эту Проблему?
Существует предложение по улучшению Java (JEP), которое предписывает использовать “UTF-8” в качестве кодировки по умолчанию в Java вместо того, чтобы основывать ее на кодировке локали и операционной системы.
Этот ДЖИП находится в состоянии проекта на данный момент и когда он (надеюсь!) пройдя через него, мы решим большинство вопросов, которые мы обсуждали ранее.
Обратите внимание, что более новые API, такие как в файле java.nio.file.Файлы не используют кодировку по умолчанию. Методы в этих API-интерфейсах читают или записывают символьные потоки с кодировкой UTF-8, а не с кодировкой по умолчанию.
6.6. Решение Этой Проблемы в Наших Программах
К счастью, наш пример уже определяет кодировку. Нам просто нужно выбрать правильный, и пусть Java сделает все остальное.
К настоящему времени мы должны понять, что акцентированные символы, такие как “ç”, отсутствуют в схеме кодирования ASCII, и поэтому нам нужна кодировка, которая включает их. Может быть, UTF-8?
Давайте попробуем это сделать, теперь мы запустим метод decode Text с тем же вводом, но с кодировкой “UTF-8”:
Бинго! Мы можем увидеть результат, который мы надеялись увидеть.
Аналогично, OutputStreamWriter и многие другие API поддерживают настройку схемы кодирования через свой конструктор.
6.7. Исключение MalformedInputException
Существует три предопределенные стратегии (или CodingErrorAction ), когда входная последовательность имеет искаженные входные данные:
По умолчанию malformedInputAction для кодера CharsetDecoder является REPORT, и по умолчанию malformedInputAction декодера по умолчанию в InputStreamReader is REPLACE.
Для третьего теста мы используем CodingErrorAction.ОТЧЕТ который приводит к выбрасыванию MalformedInputException:
7. Другие Места, Где Кодирование Важно
Нам не просто нужно учитывать кодировку символов при программировании. Тексты могут окончательно испортиться во многих других местах.
Давайте быстро рассмотрим несколько мест, где мы можем столкнуться с проблемами при кодировании или декодировании текста.
7.1. Текстовые Редакторы
В большинстве случаев текстовый редактор-это место, откуда исходят тексты. Существует множество текстовых редакторов в популярном выборе, включая vi, Блокнот и MS Word. Большинство из этих текстовых редакторов позволяют нам выбрать схему кодирования. Следовательно, мы всегда должны быть уверены, что они подходят для текста, с которым мы работаем.
7.2. Файловая система
После того, как мы создадим тексты в редакторе, нам нужно сохранить их в какой-то файловой системе. Файловая система зависит от операционной системы, на которой она работает. Большинство операционных систем имеют встроенную поддержку нескольких схем кодирования. Однако все еще могут быть случаи, когда преобразование кодировки приводит к потере данных.
7.3. Сеть
Тексты, передаваемые по сети с использованием протокола, такого как протокол передачи файлов (FTP), также включают преобразование между кодировками символов. Для всего, что закодировано в Юникоде, безопаснее всего передавать в двоичном виде, чтобы свести к минимуму риск потери при преобразовании. Однако передача текста по сети является одной из менее частых причин повреждения данных.
7.4. Базы данных
Большинство популярных баз данных, таких как Oracle и MySQL, поддерживают выбор схемы кодирования символов при установке или создании баз данных. Мы должны выбрать это в соответствии с текстами, которые мы ожидаем сохранить в базе данных. Это одно из наиболее частых мест, где повреждение текстовых данных происходит из-за преобразования кодировки.
7.5. Браузеры
Наконец, в большинстве веб-приложений мы создаем тексты и пропускаем их через различные слои с намерением просмотреть их в пользовательском интерфейсе, например в браузере. Здесь также важно, чтобы мы выбрали правильную кодировку символов, которая может правильно отображать символы. Большинство популярных браузеров, таких как Chrome, Edge, позволяют выбирать кодировку символов в своих настройках.
8. Заключение
В этой статье мы обсудили, как кодирование может быть проблемой при программировании.
Далее мы обсудили основные принципы, включая кодировку и кодировки. Более того, мы прошли через различные схемы кодирования и их использование.
Мы также подобрали пример неправильного использования кодировки символов в Java и увидели, как это сделать правильно. Наконец, мы обсудили некоторые другие распространенные сценарии ошибок, связанные с кодировкой символов.
Кодовые точки Unicode и русские символы в исходных кодах и программах Java. JDK 1.6.
Достаточно много разработчиков программного обеспечения в действительности не имеют до конца четкого представления о наборах символов, кодировок, Unicode и сопутствующих материалах. Даже в настоящее время многими программами часто игнорируются встречающиеся преобразования символов, даже программами, которые, казалось бы, разработаны с помощью дружественных к Unicode Java технологиях. Зачастую беспечно используется для символов 8 битов, что делает невозможным разработку хороших многоязычных web-приложений. Данная статья является объединением рядов статей по вопросам кодировки Unicode, однако основополагающей стала переработанная статья Джоэла Сполски The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (08.10.2003).
Весь тот материал, который говорит о том, что «простой текст = ASCII = символы из 8 бит», является не корректным. Единственными символами, которые могли отображаться корректно при любых обстоятельствах, это были английские буквы без диакритических знаков с кодами от 32 до 127. Для этих символов существует код, названный ASCII, который был в состоянии представить все символы. Буква «A» имела бы код 65, пробелом был бы код 32, и т.п. Данные символы могли быть удобно сохранены в 7 битах. Большинство компьютеров в те дни использовало 8-битовые регистры, и таким образом вы не только могли хранить любой возможный символ ASCII, но еще и имели целый бит экономии, который, если у вас была такая блажь, вы могли использовать в ваших собственных целях. Коды меньше 32 назывались непечатными и использовались для управляющих символов, например, символ 7 заставлял ваш компьютер издать сигнал динамика, а символ 12 являлся символом конца страницы, заставляя принтер прокрутить текущий лист бумаги и загрузить новый.
Поскольку байты имеют восемь битов, то многие думали: «мы можем использовать коды 128-255 в наших собственных целях». Неприятность была в том, что для очень многих эта идея пришла почти одновременно, но у всех были свои собственные идеи относительно того, что должно размещаться на месте с кодами от 128 до 255. У IBM-PC было нечто, что стало известным как набор символов OEM, в котором было немного диакритических символов для европейских языков и набор символов для рисования линий: горизонтальные полоски, вертикальные полоски, уголки, крестики, и т.д. И вы могли использовать эти символы для того, чтобы делать элегантные кнопки и рисовать линии на экране, которые вы все еще можете увидеть на некоторых старых компьютерах. Например, на некоторых PC символ с кодом 130 показывался как e, но на компьютерах, проданных в Израиле, это была еврейская буква Gimel (?). Если бы американцы посылали свои resume (резюме) в Израиль, они прибывали бы как r?sum?. Во многих случаях, как, например, в случае русского языка, было много различных идей относительно того, что делать с верхними 128 символами, и поэтому вы не могли даже надежно обмениваться русскоязычными документами.
В конечном счете, разнообразие кодировок OEM было сведено в стандарт ANSI. Стандарт ANSI, оговаривал, какие символы располагались ниже 128, эта область в основном оставалась той же, что и в ASCII, но было много различных способов обращаться с символами от 128 и выше в зависимости от того, где вы жили. Эти различные системы назвали кодовыми страницами. Так, например, в Израиле DOS использовал кодовую страницу с номером 862, в то время как греческие пользователи использовали страницу с номером 737. Они были одними и теми же ниже 128, но отличались от 128, где и находились все эти символы. Национальные версии MS-DOS поддерживали множество этих кодовых страниц, обращаясь со всеми языками, начиная с английского и заканчивая исландским, и было даже несколько «многоязычных» кодовых страниц, которые могли сделать Эсперанто и Галисийский (прим. пер.:галисийский язык относится к романской группе языков, распространён в Испании, носителей 4 млн. чел) на одном и том же компьютере! Но получить, скажем, иврит и греческий на одном и том же компьютере было абсолютно невозможно, если только вы не написали вашу собственную программу, которая показывала все, используя графику с побитовым отображением, потому что для еврейского и греческого требовались различные кодовые страницы с различными интерпретациями старших чисел.
Тем временем в Азии, принимая во внимание тот факт, что азиатские алфавиты имеют тысячи букв, которые никогда бы не смогли уместиться в 8 битов, эта проблема решалась запутанной системой DBCS, «двухбайтовый набор символов» (double byte character set), в котором некоторые символы сохранялись в одном байте, а другие занимали два. Было очень легко передвигаться по строке вперед, но абсолютно невозможно передвигаться назад. Программисты не могли использовать для перемещения вперед и назад s++ и s—, и вместо этого должны были вызывать специальные функции, которые знали, как иметь дело с этим беспорядком.
Тем не менее, большинство людей закрывало глаза на то, что байт был символом и символ был 8 битами и, пока вам не приходилось перемещать строку с одного компьютера на другой, или если вы не говорили больше, чем на одном языке, это работало. Но, конечно, как только массово стал использоваться Интернет, стало весьма обычным делом переносить строки с одного компьютера на другой. Хаос в этом вопросе был преодолен с помощью Unicode.
Unicode был смелой попыткой создать единственный набор символов, который включал бы все реальные системы письма, существующие на планете, а также некоторые выдуманые. Некоторые люди имеют неправильное представление, что Unicode – это обычный 16-битовый код, где каждый символ занимает 16 битов и поэтому есть 65,536 возможных символов. На самом деле это не верно. Это самый распространенное ошибочное представление о Unicode.
Фактически, Unicode содержит необычный подход к пониманию понятия символ. До сих пор мы предполагали, что символы отображаются на набор каких-то битов, которые вы можете хранить на диске или в памяти:
В Unicode символ отображается на нечто, называемое кодовой точкой (code point), которая является всего лишь теоретическим понятием. Как эта кодовая точка представлена в памяти или на диске — это отдельная история. В Unicode буква A это всего лишь платонова идея (эйдос) (прим. пер.: понятие философии Платона, эйдосы – это идеальные сущности, лишённые телесности и являющиеся подлинно объективной реальностью, находящиеся вне конкретных вещей и явлений).
A Эта платонова A отличается от B, и отличается от a, но это та же самая A, что и A и A. Идея, что А в шрифте Times New Roman является тем же самым, что и А в шрифте Helvetica, но отличается от строчной «a», не кажется слишком спорной в понимании людей. Но с точки зрения компьютерных наук и с точки зрения языка само определение буквы противоречиво. Немецкая буква ß – это настоящая буква или всего лишь причудливый способ написать ss? Если написание буквы, стоящей в конце слова, изменяется, она становится другой буквой? Иврит говорит да, арабский говорит нет. Так или иначе, умные люди в консорциуме Unicode поняли это, после большого количества политических дебатов, и вы не должны волноваться об этом. Все уже понято до нас.
Каждой платоновой букве в каждом алфавите консорциумом Unicode было назначено волшебное число, которое записывается так, как это: U+0645. Это волшебное число называют кодовой точкой. U+ означает «Unicode», а числа являются шестнадцатеричными. Число U+FEC9 является арабской буквой Аин (Ain). Английская буква A соответствует U+0041.
В действительности нет никакого предела для количества букв, которые могут определяться через Unicode, и на самом деле они уже перешагнули за пределы 65,536, так что не каждая буква из Unicode может действительно сжиматься в два байта.
Для кириллицы в UNICODE отведен диапазон кодов от 0x0400 до 0x04FF. В данной таблице приведена лишь часть знаков этого диапазона, однако стандартом определено большинство кодов этого диапазона.
Представим, что мы имеем строку:
которая, в Unicode, соответствует этим семи кодовым точкам:
Всего лишь набор кодовых точек. Числа в действительности.
Чтобы узнать, как будет выглядеть текстовый файл в формате Unicode, можно запустить программу notepad в Windows, вставить данную строку и при сохранении текстового файла выбрать кодировку Unicode.
Программа предлагает сохранение в трех разновидностях кодировок Unicode. Первый вариант представляет собой способ записи с младшим байтом впереди (little endian), второй со старшим байтом впереди (big endian). Какой из вариантов является правильным?