В какой кодировке хранятся символы char java
[an error occurred while processing this directive]
Java и Unicode
[an error occurred while processing this directive](none) [an error occurred while processing this directive](none)[an error occurred while processing this directive] ::
[an error occurred while processing this directive] (none)
[an error occurred while processing this directive] ([an error occurred while processing this directive] Сергей Семихатов [an error occurred while processing this directive])
[an error occurred while processing this directive](none)
- Аннотация
- Java по-русски
- Русский текст из внешнего источника
- Unicode и Java
- MBCS
- Unicode
Аннотация
Как известно, Java использует представление строк в формате Unicode. В этой статье речь пойдет о способах хранения и представления данных, записанных в разных кодировках.
Java по-русски
Написать java-апплет, выводящий приветствие на русском языке очень просто. Можно вставить строку с русским языком прямо внутрь текста класса:
String labelName = "Привет!"; JLabel myLabel = new JLabel(labelName);
Однако не факт, что это будет работать. Ведь тот русский текст, который был набран в редакторе, мог существовать практически в любой кодировке (DOS/Win/UNIX). Исходный текст программы обычно представлен в 8-битном формате, а один символ (char) в java занимает 2 байта (это связано с тем, что язык java ориентирован на поддержку и на работу с Unicode). Таким образом при компиляции программы происходит преобразование символов из одной кодировки (кодировки редактора) в другую (Unicode).
Это преобразование (перекодировка) основывается на том, что исходный текст программы написан в той же кодировке, что и базовая кодировка Java Virtual Machine (JVM), которая, как правило, совпадает с кодировкой самой операционной системы (для русских Windows это будет Cp1251). Таким образом, если кодировка кириллицы в редакторе совпала с кодировкой кириллицы в системе, то сообщение «Привет!» появится в нормальном виде.
Чтобы избежать путаницы с кодировками русского языка в тексте программы, у компилятора javac есть специальный параметр encoding , который определяет кодировку исходного текста программы.
Есть и другой способ. Русские буквы в тексте программы можно указывать в формате `\uXXXX’ (где XXXX — шестнадцатиричный код символа в стандарте Unicode). В комплект JDK входит утилита native2ascii , которая позволяет перевести текст из любой поддерживаемых JDK кодировок в ASCII-вид, а символы, не имеющие отображения в ASCII, представить в `\uXXXX’ виде. Узнать код того или иного символа кириллицы в Unicode можно, запустив программу charmap в WindowsNT.
Русский текст из внешнего источника
Как показать русский текст из внешнего источника, например файла? Текст в файле хранится, как правило, в 8-битном формате. Для чтения/записи и преобразования набора байт в строку и обратно используются специальные классы из пакета java.io : InputStreamReader и OutputStreamReader.
Эти два класса специально предназначены для преобразования потока байт в указанной кодировке (чем по умолчанию является кодировка системы) в Unicode строку java.
Вот типичный пример создания «читателя» из файла:
FileInputStream fis = new FileInputStream("priwet.txt"); InputStreamReader isr = new InputStreamReader(fis, "Cp1251"); Reader in = new BufferedReader(isr);Unicode и Java
Предположим, однако, что необходимо работать с внешним текстом (или данными) не только в русской, а в любой кодировке. Эту проблему можно решить двумя способами: храня внешние данные в формате Unicode или же в формате MBCS (MultiByte Character Set).
MBCS
Несмотря на то, что Unicode был специально разработан для поддержки многих языков, использовать его для хранения и передачи строк в Америке и большей части Европы неэффективно, потому что для этих регионов достаточно 256, а иногда всего 128 символов. Ведь первые 128 символов Unicode (\u0000 — \u007F) совпадают с ISO-646, а первые 256 символов (\u0000 — \u007F) совпадают с ISO-8859-1. Тем самым, используется только маленький кусочек всего спектра Unicode, ведь старший байт почти всегда равен нулю.
Возникает желание по-прежнему использовать Unicode внутри программы, но хранить и передавать данные в 8-битной кодировке, преобразуя данные непосредственно перед их получением или записью. В качестве записи в 8-битной кодировке можно использовать технологию MBCS, где каждый символ может занимать несколько байт.
Вопрос заключается в том, какой набор символов (кодировку) использовать для такого преобразования. Существующие кодировки не подходили для этой цели, поэтому Unicode Consortium выработал специальные кодировки для преобразования Unicode-строк в MBCS-строки. Эти кодировки носят название Unicode Transformation Format (UTF), и существуют в двух вариантах: UTF-7 и UTF-8. Они различаются количеством бит (7 или 8), используемых для кодирования.
Кодировка UTF-7 характерна тем, что часто требует больше байтов для представления данных, чем сам Unicode. Но эта кодировка необходима, так как многие старые системы (и не только, например, MIME) используют 7-битную кодировку символов.
Кодировка UTF-8, в свою очередь, очень хорошо подходит для хранения текста, который используют ASCII символы, и символы, чей Unicode код меньше \u0800. В этом спектре лежит большинство символов, используемых в европейских (соответственно, и американских) и ближневосточных странах. Для символов, чей код больше \u07FF, UTF-8, наоборот, мало подходит, потому что эти символы расплываются до 3 байт.
Алгоритмы конвертации между Unicode и UTF-7 или UTF-8 описаны в стандарте Unicode (The Unicode Standart).
Unicode
Чтобы узнать, как будет выглядеть текстовый файл в формате Unicode, можно запустить программу notepad в WindowsNT и при сохранении текстового файла поставить галочку «Сохранить в формате Unicode».
Рисунок 1.
Так как каждый символ занимает 2 байта, то возникает проблема, в каком порядке они должны быть записаны. Рассмотрим строку «Привет!». Возможны два варианта:
-
младший байт впереди (little endian)
04 40 04 38 04 32 04 35 04 42 04 21 00
40 04 38 04 32 04 35 04 42 04 21 04 00
Какой из вариантов является правильным? В стандарте Unicode написано, что порядок байт по умолчанию является либо big endian, либо little endian 🙂
Действительно, оба порядка являются правильным, и разработчики систем сами выбирают себе один из них. Так что нечего беспокоиться, если ваша Windows NT Workstation обменивается данными с Windows NT Server — они обе используют little endian.
Однако, если ваша Windows NT Workstation обменивается данными с UNIX-сервером, который использует big endian, одна из систем должна осуществлять перекодировку. В этом случае стандарт Unicode гласит, что можно выбрать любой из следующих способов решения проблемы:
- Когда две системы, использующие различный порядок представления байт в Unicode, обмениваются данными (не используя каких-то специальных протоколов), то порядок байт должен быть big endian. В стандарте это называется каноническим порядком байт. Однако второй способ является более универсальным и предпочтительным:
- Каждая строка Unicode должна начинаться с кода \uFEFF, который в стандарте называется «знаком порядка» (byte order mark) или «zero-width nonbreaking space». Код \uFFFE, который является «перевертыванием» знака порядка, не обозначает ничего (так он зарезервирован в стандарте Unicode). Поэтому если получатель видит в качестве первого символа код \uFEFF, то это значит, что байты находятся в перевернутом (little endian) порядке.
Вот как выглядит файл со строкой «Привет!», сохраненный в формате Unicode:

Рисунок 2.
Для чтения данных, записанных как в формате MBCS (используя кодировку UTF-8), так и в формате Unicode, можно использовать все тот же класс InputStreamReader из пакета java.io , подставляя в его конструктор различные кодировки. В описании пакета java.lang написано, что каждая реализация JVM должна поддерживать следующие кодировки:
US-ASCII семибитная ASCII, она же ISO646-US, она же основная латинская часть Unicode; ISO-8859-1 то же самое, что ISO-LATIN-1; UTF-8 8-битный Unicode Transformation Format; UTF-16BE 16-битный Unicode Transformation Format, порядок байт big-endian; UTF-16LE 16-битный Unicode Transformation Format, порядок байт little-endian; UTF-16 16-битный Unicode Transformation Format, порядок байт определяется начальными значениями (допускается любой), на выходе порядок байт big-endian. Для чтения файла в формате Unicode надо использовать значение «UTF-16», а для чтения файла в формате UTF-8 — использовать «UTF-8»:
FileInputStream fis = new FileInputStream("priwet_u.txt"); InputStreamReader isr = new InputStreamReader(fis, "UTF-16");Преобразование между строками и потоком байт
В java для преобразования потока байт (byte[]) в строку (String) и обратно, в классе String есть следующие возможности:
- Конструктор String(byte[] bytes, String enc) получает на вход поток байт с указанием их кодировки; если кодировку опустить то она будет принята по умолчанию
- Метод getBytes(String enc) возвращает поток байт, записанных в указанной кодировке; кодировку также можно опустить.
try < String priwet = new String( "\u041F"+"\u0440"+"\u0438"+ "\u0432"+"\u0435"+"\u0442"+"!"); byte[] utf8Bytes = priwet.getBytes("UTF8"); String priwet2 = new String(utf8Bytes,"UTF8"); >catch (UnsupportedEncodingException e)
[an error occurred while processing this directive]
[an error occurred while processing this directive] (none)- Статьи
- Java: Русские буквы и не только.
- Почтовая программа — своими руками!
- LiveConnect: руководство для IE
- Доступ к COM порту из Java приложения
- Технологии построения распределенных объектных систем
- Java и Unicode
- Простое CORBA приложение — своими руками
- Разработка Java приложений для Lotus Notes
- Множественное наследование в Java. Противоречия и способы их решения
- Динамическая связь интерфейсов и реализации в JDK 1.3
- Оптимизация загрузки классов
- Реализация алгоритма вычисления CRC-16 средствами Java2 для передачи данных по протоколу MODBUS режим RTU
- Анализ покрытия как метод улучшения качества кода
- Использование аннотаций в J2SE 5
- Использование параметризуемых классов в J2SE 5
- Конфигурация JAVA приложения с помощью XML
< Вернуться на caйт:: Copyright © 1999 — 2010, IT • archiv. Pro Java
Хоть тип char и относится к целочисленным типам, но все же он стоит несколько особнячком, так как предназначен для представления отдельных символов Unicode. Поэтому его рассмотрим отдельно от целочисленных типов, хотя над ним можно совершать все те же самые операции, что и над целочисленными типами (сложение, вычитание и т.д. и т.п.). Но в тоже время им можно задавать значения при помощи символьных литералов, например ‘A’ – то есть любым символом заключенным в одинарные кавычки , но не стоит это путать со строкой “А”, состоящей из одного символа.
Как уже упоминалось размер этого типа равен 16 битам и поэтому может содержать значения от 0 до 65535 в десятичном исчислении. Отрицательных значений для типа char не существует . Это единственное без знаковый целочисленный тип данных в Java.
Задавать значения типа char можно при помощи следующих литералов или управляющих символов, например:
Символьные литералы
‘A’ – символьный литерал, заданный напрямую любым отображаемым символом Unicode
‘\uxxxx’ – символ Unicode, где xxxx цифровой код символа Unicode в шестнадцатеричной форме
‘\xxx’ – символ кодовой таблицы Latin-1, где xxx восьмеричный код символа Latin-1
1046 – код символа Unicode в десятичном исчислении
0x0950 – код символа Unicode в шестнадцатеричном форматеПоскольку char – это целочисленный тип, то ему можно присваивать значения всеми теми же литералами, что и другим целочисленным, это могут быть и двоичные и восьмеричные литералы, только в этом нет ни какого смысла и это даже не удобно.
Управляющие символы (так же должны быть заключены в одинарные кавычки):
\b – backspase BS – забой (\u0008 в кодировке Unicode и 8 в десятичной)
\t – horizontal tab HT – табуляция (\u0009 в кодировке Unicode и 9 в десятичной)
\n – line feed LF – конец строки (\u000a в кодировке Unicode и 10 в десятичной)
\f – form feed FF – конец страницы (\u000с в кодировке Unicode и 12 в десятичной)
\r – carriage return CR – возврат каретки (\u000d в кодировке Unicode и 13 в десятичной)
\” – двойная кавычка (\u0022 в кодировке Unicode и 34 в десятичной)
\’ – одинарная кавычка (\u0027 в кодировке Unicode и 39 в десятичной)
\\ – backslash \ – обратная косая черта (\u005c в кодировке Unicode и 92 в десятичной)Для справки про запись символов в восьмеричной системе счисления: код любого символа с десятичной кодировкой от 0 до 255 можно задать, записав его не более чем тремя цифрами в восьмеричной системе счисления в апострофах после обратной наклонной черты: ‘ \123’ — буква S, ‘ \346’ — буква Ж в кодировке CP1251. Особого смысла нет использовать эту форму записи для печатных и управляющих символов, перечисленных в предыдущем пункте, поскольку компилятор сразу же переведет восьмеричную запись в шестнадцатеричную. Наибольший восьмеричный код
‘ \377’ — десятичное число 255.ПРИМЕЧАНИЕ
Прописные русские буквы в кодировке Unicode занимают диапазон от ‘\u0410’ — заглавная буква А, до ‘\u042F’ — заглавная Я, строчные буквы от ‘\u0430’ — а, до ‘\u044F’ — я.Из этого ряда выпала только буква Ё. Ну ё маё Но все же она представлена в Unicode.
Заглавная Ё – ‘\u0401’, и строчная ё – ‘\u0451’.
Ну а теперь немножко попрактикуемся, чтобы не было скучно, и продолжим, так как это еще не все с типом char.

Как видно из скрина программы, значения переменным типа char можно задавать разными способами, как через десятичный код символа, так и через шестнадцатеричный, а для управляющих символов доступны кроме кодов еще и сами управляющие символы.
Ради прикола я создал переменную с идентификатором ё, который вполне допустив в Java, так как Java использует символы Unicode даже для записи кода самой программы.
Вывод программы в консоли Eclipse такой:

Как видим отработали наши символы табуляции, которые мы использовали, а так же оператор print(), который печатает без перевода на новую строку. Кроме того фразу Hello World мы заключили в двойные кавычки и немного ее разбили символом перевода строки и двумя символами табуляции.
Затем, в строке 22, мы увеличили значение переменной ё на единицу и снова вывели результат.
Таким образом видно, что примитивный тип char это целочисленный тип, над которым возможны все те же самые операции, что и над другими целочисленными типами.
В Eclipse эта программа запускается нормально, а вот в консоли это уже совсем другой кордебалет.

Ну что? Потанцуем?
Прежде чем запускать эту программу, во первых надо задать для консоли кодировку UTF8, а затем запускать саму программу следующей командой:
java -Dfile.encoding=UTF-8 CharType
Это необходимо делать, так как при выводе на консоль виртуальная машина java делает обратное преобразование из кодировки UTF8 в кодировку операционной системы, для Windows это 1251 или 866 в консоли.
CharType – это не параметр, это программа так называется, вернее класс.
Надо отметить, что если у вас нет каких-то специальных символов и вы просто используете русский язык под Windows, то все эти танцы с бубнами не нужны. Они так же не нужны если вы пишете под Mac OS X на Java, поскольку консоль там нативно поддерживает Unicode.
Стоит так же упомянуть, что на нынешний момент количество символов Unicode уже превышает 65536, поэтому с Java 5 для работы с этими символами было введено понятие суррогатной пары, поскольку 16 разрядного типа char уже стало не хватать. Для работы с этими символами используется две переменные типа char. Первый символ в паре обозначающих один символ Unicode называется high surrogate, а второй – low surrogate, а вместе они называются суррогатной парой и их обоих так же можно хранить в переменной типа int.
На практике, использование суррогатной пары, встречается чрезвычайно редко, но знать об этом следует. Более подробно об Unicode в Java и кодовых точках можно почитать тут и тут. И еще тут.

Приведу простой пример по работе с суррогатной парой в Java, чтобы было хоть какое-то представление. В примере, естественно, есть вещи которые еще мы не проходили, такие как циклы, массивы, условные проверки и т.п., но надеюсь что все будет понятно.
Данная программа проверяет является ли суррогатная пара допустимым значением и если да, то выводит этот символ на экран, а так же выводит код кодовой точки.
В данном случае выводится символ ракеты представленной кодом UTF-16BE 0xD83D и 0xDE80, что соответствует кодовой точке 128640.
Как видно в примере переменным типа char значения заданы при помощи шестнадцатеричных цифровых литералов.

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

Ну а теперь посмотрим на вывод этой программы в консоли Eclipse

И в консоли Windows


В принципе ракету можно узнать в этом символе . Сразу же хочу отметить, что консоли Eclipse и Windows могут отобразить далеко не все дополнительные символы Unicode.
На этом с char пока все. И еще пара ссылок по теме Unicode тут и тут.
Как кодировка *.java файла влияет на тип char в Java?
Почему данный фрагмент кода выводит 0 , если кодировка кода в Windows-1251 и 15 если кодировка UTF-8 ?
String s1 = "П"; String s2 = "А"; System.out.println(s1.compareTo(s2));В таблице UTF-8 отсутствует кириллица, а в Windows-1251 есть все кириллические символы. Поправьте, если ошибаюсь.
Отслеживать
1,745 9 9 золотых знаков 19 19 серебряных знаков 28 28 бронзовых знаков
задан 20 окт 2015 в 6:12
Anatoly Samokisha Anatoly Samokisha
282 1 1 серебряный знак 14 14 бронзовых знаковЭто шутка да: «В таблице UTF-8 отсутствует кириллица» i.voenmeh.ru/kafi5/Kam.loc/inform/UTF-8.htm Зачем бы был нужен unicode
20 окт 2015 в 6:21
«0 если кодировка кода в Windows-1251 и 15 если кодировка UTF-8» как это было проверено?
20 окт 2015 в 6:31@VladislavPyatkov Искал в google таблицы, нашел эти goo.gl/r0B3e goo.gl/EcBD9h. Судя по вашей таблице ‘А’ в DEC 208144 в win-1251 192, а диапазон char 0-65535. Проверял скомпилировав в разных кодировках.
20 окт 2015 в 6:37
В java строки и символы всегда UTF, никак такой код 0 не вернёт. Вот так можете сделать System.out.println(s1.compareTo(s2) == 0);
20 окт 2015 в 6:48
@VladislavPyatkov я делаю вот так System.out.println(s1.compareTo(s2) != 0); Но всегда было false, пока кодировку не поменял. В IDEA по умолчанию Windows-1251 для новых проектов.
20 окт 2015 в 6:56
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
public class Cp1251Src < public static void main( String[] args ) < String s1 = "П"; String s2 = "А"; System.out.println(s1.compareTo(s2)); >>Сохраним файл в кодировке cp1251, попробуем собрать javac 1.8.0_45 с указанием правильной кодировки:
>javac -encoding cp1251 Cp1251Src.java >java Cp1251Src 1515 — правильный ответ, т.к. String.compareTo возвращает разность первых отличающихся символов.
Укажем неправильную кодировку:
>javac -encoding utf8 Cp1251Src.java Cp1251Src.java:3: error: unmappable character for encoding utf8 String s1 = "?"; ^ Cp1251Src.java:4: error: unmappable character for encoding utf8 String s2 = "?"; ^ 2 errorsjavac отказывается компилировать, т.к. не может преобразовать байты файла в символы, используя указанную кодировку.
IDEA у меня нет, но есть Eclipse. Если в нем указать кодировку файла UTF-8, то вместо «А» и «П» будет виден символ «�» (U+FFFD, REPLACEMENT CHARACTER). Код успешно скомпилируется, выполнится и выведет 0, т.к. строки теперь равны.
Т.е. там, где javac из-за ошибки преобразования байт в символы отказывается продолжать работу, Eclipse (и, скорее всего, Idea), заменяют непреобразуемые байты на U+FFFD, и работает дальше.
А если файл, сохраненный в кодировке Utf-8 скомпилировать с параметром -encoding cp1251 , программа выведет 13.
В какой кодировке хранятся символы char java
Статья опубликована: 06.11.2006
Последнее обновление : 18.03.2007
История создания различных видов кодировок
Весь тот материал, который говорит о том, что «простой текст = ASCII = символы из 8 бит», является не корректным. Единственными символами, которые могли отображаться корректно при любых обстоятельствах, это были английские буквы без диакритических знаков с кодами от 32 до 127. Для этих символов существует код, названный ASCII , который был в состоянии представить все символы. Буква «A» имела бы код 65, пробелом был бы код 32, и т.п. Данные символы могли быть удобно сохранены в 7 битах. Большинство компьютеров в те дни использовало 8-битовые регистры, и таким образом вы не только могли хранить любой возможный символ ASCII, но еще и имели целый бит экономии, который, если у вас была такая блажь, вы могли использовать в ваших собственных целях. Коды меньше 32 назывались непечатными и использовались для управляющих символов, например, символ 7 заставлял ваш компьютер издать сигнал динамика, а символ 12 являлся символом конца страницы, заставляя принтер прокрутить текущий лист бумаги и загрузить новый.
Поскольку байты имеют восемь битов, то многие думали: «мы можем использовать коды 128-255 в наших собственных целях». Неприятность была в том, что для очень многих эта идея пришла почти одновременно, но у всех были свои собственные идеи относительно того, что должно размещаться на месте с кодами от 128 до 255. У IBM-PC было нечто, что стало известным как набор символов OEM, в котором было немного диакритических символов для европейских языков и набор символов для рисования линий: горизонтальные полоски, вертикальные полоски, уголки, крестики, и т.д. И вы могли использовать эти символы для того, чтобы делать элегантные кнопки и рисовать линии на экране, которые вы все еще можете увидеть на некоторых старых компьютерах. Например, на некоторых PC символ с кодом 130 показывался как é , но на компьютерах, проданных в Израиле, это была еврейская буква Gimel ( ג ). Если бы американцы посылали свои résumé (резюме) в Израиль, они прибывали бы как 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 , соответствует этим семи кодовым точкам:
U+ 041 F U+0440 U+0438 U+0432 U+0435 U+0442 U+0021
Всего лишь набор кодовых точек. Числа в действительности.
Чтобы узнать, как будет выглядеть текстовый файл в формате Unicode , можно запустить программу notepad в Windows , вставить данную строку и при сохранении текстового файла выбрать кодировку Unicode .
Программа предлагает сохранение в трех разновидностях кодировок Unicode . Первый вариант представляет собой способ записи с младшим байтом впереди ( little endian ), второй со старшим байтом впереди ( big endian ). Какой из вариантов является правильным?
Вот как выглядит дамп файла со строкой “ Привет! ”, сохраненный в формате Unicode ( big endian ):

А так выглядит дамп файла со строкой “ Привет! ”, сохраненный в формате Unicode ( little endian ):

А так выглядит дамп файла со строкой “ Привет! ”, сохраненный в формате Unicode ( UTF -8):

Ранние реализации хотели быть в состоянии хранить кодовые точки Unicode в формате с первым старшим байтом и первым младшим байтом ( high-endian or low-endian ), в зависимости от того, с каким форматом именно их процессор работал быстрее. Тогда возникло два способа хранить Unicode . Это привело к появлению причудливого соглашения о хранении кода \ uFFFE в начале каждой строки Unicode . Эту сигнатуру называют меткой порядка байтов ( byte order mark ). Если вы поменяете местами ваши старший и младший байты, то в начале должно стоять \ uFFFE , и человек, читающий вашу строку, будет знать, что он должен поменять байты в каждой паре местами. Данная сигнатура является зарезервированной в стандарте Unicode .
В стандарте Unicode написано, что порядок байт по умолчанию является либо big endian , либо little endian . Действительно, оба порядка являются правильным, и разработчики систем сами выбирают себе один из них. Не стоит беспокоиться, если ваша система обменивается данными с другой системой и обе используют little endian .
Однако , если ваша Windows обменивается данными с UNIX-сервером, который использует big endian , одна из систем должна осуществлять перекодировку. В этом случае стандарт Unicode гласит, что можно выбрать любой из следующих способов решения проблемы:
1. Когда две системы, использующие различный порядок представления байт в Unicode , обмениваются данными (не используя каких-то специальных протоколов), то порядок байт должен быть big endian . В стандарте это называется каноническим ( canonical ) порядком байт.
2. Каждая строка Unicode должна начинаться с кода \ uFEFF . Код \ uFFFE , который является “перевертыванием” знака порядка. Поэтому если получатель видит в качестве первого символа код \ uFEFF , то это значит, что байты находятся в перевернутом ( little endian ) порядке. Тем не менее, в реальности, не каждая строка Unicode имеет в начале метку порядка байтов.
Второй способ является более универсальным и предпочтительным.
Некоторое время казалось, что все довольны, но англоязычные программисты рассматривали в основном английский текст и редко использовали кодовые точки выше U+00FF. По одной только этой причине Unicode многими игнорировался в течение нескольких лет.
Специально для этого была изобретена блестящая концепция UTF-8 .
UTF -8
UTF-8 был другой системой хранения вашей последовательности кодовых точек Unicode , тех самых U+ чисел, используя те же 8 битов в памяти. В UTF-8 каждая кодовая точка с номерами от 0 до 127 сохранялись в единственном байте.
По сути, это кодировка с переменным количеством кодирующих байтов для хранения используется 2, 3, и, фактически, до 6 байтов. Если символ принадлежит набору ASCII (код в интервале 0x00-0x7F), то он кодируется так же как в ASCII одним байтом. Если юникод символа больше или равен 0x80, то его биты упаковываются в последовательность байтов по следующему правилу:
