Pull to refresh

Comments 11

Ваша статья вводит в заблуждение относительно UCS и UTF. UCS2 и UCS4 не имеют «байтового» представления, как не имеет его, например, unsigned long long или int, поэтому говорить UCS-2BE — некорректно и не имеет смысла.

Юникодные строки состоят из codepoint-ов. Codepoint — это просто число в открытом диапазоне [0..0x110000), и у этого числа не определено бинарное представление. UCS4 позволяет представлять codepoint-ы как, как минимум, 32-битные беззнаковые целые — но только для использования в памяти, т.к. бинарное представление в UCS4 не определено.

Как вариант, UCS2 представляет codepoint-ы, как 16-ти битные беззнаковые целые, но при этом обрезает кодовое пространство до открытого диапазона [0..0x10000) (т.н. базовая плоскость), и в UCS2 выразить символы из дополнительной плоскости невозможно. UCS2, очевидно, является подмножеством UCS4, и как и UCS4, не имеет бинарного предствления.

Т.е. UCS2 и UCS4 — это способы исключительно внутреннего представления юникодных строк программами, которые работают с юникодными строками.

Поэтому и нужны «форматы трансформации Юникода» (Unicode transformation formats, UTF) — UTF-8, UTF-16 и UTF-32. Они определяют правила для преобразования каждого codepoint-а в один или больше unit-ов, которые и есть базовая единица бинарного представления.

UTF-32 транслирует каждый codepoint в один unit размером в 32 бита. В зависимости от порядка байт, его можно записать как UTF-32BE или UTF-32LE.

UTF-16 ставит в соответствие каждому codepoint-у один или два unit-а, каждый 16 бит размером. Два unit-а UTF-16 образуют суррогатную пару, которая декодируется в один code point. Суррогатные пары используются, чтобы выразить символы из дополнительных плоскостей — т.е. те, которые не может выразить UCS2.

UTF-8 преобразовывает каждый codepoint в от одного до четырех (или до шести в более старом стандарте Unicode) code unit-ов, и каждый занимает в точности 8 бит.

Надеюсь, мой комментарий немного прояснил ситуацию.
Спасибо за комментарий.
Вопрос не вполне однозначный, давайте попробуем разобраться. Я предложил простую схему:
UCS-2 для старого unicode, когда использовалась только одна плоскость;
UTF-16 для нового, когда их стало 17 и потребовались суррогатные пары;
Почему-то UTF-16 в применении к UCS-2 мне не попадалась.

Может, мое описание не совсем точно, зато просто и понятно и при описании языков программирования (Java, например) UCS-2 чаще трактуется как урезанный UTF-16 (без суррогатных пар), а не как абстактная точка кодовая пространства.
Вы предлагаете UCS-2 как идею точки в кодовам пространстве. Хорошо, тогда ответьте на вопрос: как хранились символы Unicode в файлах, когда была только одна плоскость? Был ли это фиксированный порядок или он мог быть разным? Как назывался этот разный порядок? Наберите в Google UCS-2 Little Endian (хотя это некорректно) и получите десятки тысяч ссылок
Впрочем, не хочется уподобляться остро и тупо-конечникам. Чем больше значений (даже не вполне точных/корректных) мы знаем — тем лучше (если, конечно, хотим понимать друг-друга, а не бороться за чистоту языка).

Я предложил простую схему:
UCS-2 для старого unicode, когда использовалась только одна плоскость;
UTF-16 для нового, когда их стало 17 и потребовались суррогатные пары;
Имеет смысл смотреть на восьмибитные кодовые страницы, потому что это прошлое, которое все еще где-то используется в настоящем. Но зачем думать о «старом Unicode», который нигде, абсолютнейше нигде не используется? Это неудачные версии, которые были рождены в поисках. Сейчас у Unicode множество плоскостей, и следует исходить именно из этого. Более того, использовать где-либо UCS2 вместо UCS4 — плохая идея, китайские пользователи и любители emoji скажут огромное «спасибо» за невозможность использовать привычные символы.

Почему-то UTF-16 в применении к UCS-2 мне не попадалась.
Вы никогда не можете знать, попадалась или нет. Если вы видите что-то, что вы думаете, что является UCS-2 — это UTF-16, и неважно, есть ли в нем суррогатные пары или нет. То, что их нет в этом отдельно взятом тексте, не означает, что их там не может быть.

Может, мое описание не совсем точно, зато просто и понятно и при описании языков программирования (Java, например) UCS-2 чаще трактуется как урезанный UTF-16 (без суррогатных пар), а не как абстактная точка кодовая пространства.
А вот за это стоит пороть патчкордом на конюшне. Это настолько дремучее наплевательство на стандарты — просто выкинуть все, кроме BMP — что у меня нет приличных слов, чтобы описать мое отношение к подобным затеям.

Вы предлагаете UCS-2 как идею точки в кодовам пространстве.
Нет, не совсем. UCS-2 и UCS-4 — это внутренние представления точек в кодовом пространстве. UCS-2 — урезанное, которое более не стоит использовать, и UCS-4 — включающее весь современный Unicode. И это не я предлагаю, а консорциум Unicode. Естественно, архитектор может выбрать использовать в качестве внутреннего представления строк в программе не UCS, а, например, UTF8. Это имеет смысл, когда нужно сохранить совместимость с char * — но на самом деле, когда будет осуществляться работа с этими строками — придется все же выбрать, какие codepoint-ы использовать для декодированных представлений — 16 или 32-битные — UCS-2 или UCS-4.

Хорошо, тогда ответьте на вопрос: как хранились символы Unicode в файлах, когда была только одна плоскость?
Отвечу запросом на запрос — а как хранились символы Unicode в файлах, когда Unicode не было? Изначальная идея с «64к символов хватит всем» на практике оказалась неудачной, поэтому нет больше смысла потрясать ISO 10646, в котором UCS-2 имел бинарное представление и в каких-то аспектах был похож на современный UTF-16.

Был ли это фиксированный порядок или он мог быть разным? Как назывался этот разный порядок? Наберите в Google UCS-2 Little Endian (хотя это некорректно) и получите десятки тысяч ссылок
Эти десятки тысяч ссылок либо относятся к ошибкам использования терминологии, когда хотят сказать UTF-16, но говорят UCS-2; либо к тем временам, когда UTF еще не было, и только UCS-2 носился над водой; либо к тем кастрированным, наплевательским реализациям, которые считают, что в UTF-16 нет суррогатных пар. Последним — стыд и позор.

Впрочем, не хочется уподобляться остро и тупо-конечникам. Чем больше значений (даже не вполне точных/корректных) мы знаем — тем лучше (если, конечно, хотим понимать друг-друга, а не бороться за чистоту языка).
Ради облегчения понимания я и оставил свой комментарий, так как когда выполнял работу по перестройке громаднейшего C-проекта с исключительно cемибитных ASCII-строк на полную поддержку Unicode, уже успел собрать все грабли, включая терминологические, архитектурные и практические.
Это статья (в паре со статьей о кодировках) написана, чтобы программистам было понятнее, что такое UTF-16BE/LE, UTF-8, что такое и зачем нужен BOM, как символы хранятся в памяти и в файлах. Чтобы им было легче понять, почему у них в программе читаются/пишутся «кракозябры».

Извиняюсь, если вместо понимания я невольно ввел в заблуждение. Но ведь по Unicodee есть масса других статей, где-то более правильных и интересных. Я написал такую, какую сам бы хотел прочитать лет 5 назад… Кстати, первый вариант опубликован пару лет назад, но ЖЖ не дает поисковикам индексировавать начинающих авторов. А если статьи нет в поисковике — ее, считай, нет в интернете.
Чего? Если формат не известен, то это utf8. Или я что-то не понимаю? java и windows застряли на 16 битах и хаках вокруг них, нормальный юникс сел на utf8 и с тех пор с ним всё хорошо настолько мало плохо, насколько может быть.
Кстати, раз уж в одной статье упомянуты и суррогатные пары, и UTF-8, возможно вам будет интересно почитать про CESU-8 и WTF-8.

Tl;dr: суррогаты в utf-8 нельзя, но если очень хочется и никто не узнает, то можно.
Лирическое отступление: несколько лет назад телепузики прислали расшифровку звонков, одолел ее только Штирлиц — они прислали страницу в КОИ-5!!!
Телетайп с 5-дорожечной перфолентой помню, а вот как называлась используемая им кодировка — забыл (но кажется, не КОИ-5...)
Кстати, хотя телетайп печатал медленней электрической машинки «Консул», зато он в отличии от нее никогда не сбивался. А у «Консула» рычажки заклинивались и печать прерывалась.
Так этот код назвал Штирлиц, сам я сталкивался с перфолентой только когда с парней на кафедре потребовали считать архив. Электронику они сделали, но юстировать механику и оптику фотосчитки от «Наири-К» позвали меня, выдали пару баллонов пива и метровый обрывок ленты. Через полчаса на экране ХТ появился осмысленный обрывок программы.
Sign up to leave a comment.

Articles