LINUX.ORG.RU

вопрос про юникод

 , ,


0

1
$ python
Python 3.6.4 (default, Jan  5 2018, 02:35:40) 
[GCC 7.2.1 20171224] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print(bytes("И", "utf-8"))
b'\xd0\x98'
>>> print("\ud098")
킘
>>> print("\u98d0")
飐
>>> 

разве не должно быть «И» в одном из print'ов?

$ echo "И" > test
$ cat test 
И
$ hexdump test 
0000000 98d0 000a                              
0000003
$ 

я точно чего то не знаю о юникоде. и в его стандарте вроде какой то другой диапазон для русских букв.

Перемещено leave из talks


разве не должно быть «И» в одном из print'ов?

Нет.

я точно чего то не знаю о юникоде.

Да. Почитай, что такое UTF-8 и что такое code point.

>>> print(bytes("И", "utf-8"))
b'\xd0\x98'

Это вывод в кодировке UTF-8.

>>> print("\ud098")
킘
>>> print("\u98d0")
飐

А здесь ты должен вводить code point, а не UTF-8. Кириллическая заглавная «И» («Cyrillic Capital Letter I») — это code point U+0418, т. о.:

>>> print("\u0418")
И
intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от intelfx

так почему он в файле сохраняется не как «04 18» а как «98 d0». откуда вообще берётся «98 d0»?

iluha16
() автор топика
Ответ на: комментарий от iluha16

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

#include<stdio.h>
void main()
{ 
  char txt[3]={0xd0,0x98,0x0};
  printf("%s\n",txt);
}

Вот:

$ gcc u.c -o u
$ ./u
И

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от anonymous_incognito

По-моему, это python-специфика какая-то и понимать надо не в юникоде, а в работе с ним питона.

Нет, ты не прав. В Си «вывод кодов в консоль нормально отрабатывает» тупо потому что Си не знает ни о каком Юникоде и печатает байты. Так получилось, что нативная кодировка твоей консоли (UTF-8) совпала с кодировкой символа «И» в массиве txt.

А в питоне Юникод поддерживается нативно, т. е. в строках хранятся code-point'ы (не зависящие от кодировок), а при выводе перекодируются в кодировку консоли.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

что такое code-point? зачем одному символу присваивать 2 номера один codepoint и ещё один какой то другой? по какому алгоритму преобразуются эти номера?

iluha16
() автор топика
Ответ на: комментарий от iluha16

Я уже достаточно объяснил в своём первом ответе. Дальше — читай документацию по Юникоду. Копипастить оттуда определения я не буду, сам найдёшь.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Так получилось, что нативная кодировка твоей консоли (UTF-8) совпала с кодировкой символа «И» в массиве txt.

Иначе смысла бы не было, если бы консоль была не utf-8 Но штука в том, что utf-8 специально был разработан, так чтобы программы, даже ничего не знающие про неё, могли тем не менее, корректо её обрабатывать просто как поток байтов.

В Си «вывод кодов в консоль нормально отрабатывает» тупо потому что Си не знает ни о каком Юникоде и печатает байты.

Именно на это и расчёт.

anonymous_incognito ★★★★★
()
Ответ на: комментарий от iluha16

Это удачно что он еще не побил тебя. Яю не сдержался

demrnd
()
Ответ на: комментарий от iluha16

объяснил бы простым языком

Если грубо, то юникод это перечень символов. Все символы пронумерованы, поэтому некотому числу соответствует некоторый символ, и наоборот. На самом деле, там сложнее, но в первом приближении можно считать так. Этих символов намного больше 256, поэтому не получится в один байт (0-255) записать один символ. А как-нибудь байтами записывать хочется, хотя бы для того, чтобы текст в файл сохранить. Для этого есть кодировки. Это правила, по которым номер символа преобразуется в набор байт, и наоборот, набор байт преобразуется в номер символа.

Ты, наверное, думаешь, что можно просто взять и записывать. Если у символа номер 0x20, то писать 0x20. А если номер 0x418, то писать 0x04 0x18. Но это не сработает, потому что будет путаница при декодировании. Поэтому правила в кодировках сложнее.

Дальше читай статью про UTF-8 на википедии.

i-rinat ★★★★★
()
Ответ на: комментарий от intelfx

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

iluha16
() автор топика
Ответ на: комментарий от intelfx

Я уже достаточно объяснил в своём первом ответе. Дальше — читай документацию по Юникоду. Копипастить оттуда определения я не буду, сам найдёшь.

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

Просто CodePoint - это не что-то особенное, а номер символа в UTF-16, в форме \u0418 - это шестнадцатиричный номер «И» в таблице UTF-16, где для кириллицы отведены места от 0400 до 04FF.

utf-8 - это схема кодирования UTF-16 переменным числом байт в однобайтной последовательности. Для 0x0418 - это будут два _отдельных_ байта 0xd0 и 0x98

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от i-rinat

От ты пустослов.

Дальше читай статью про UTF-8 на википедии.

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

Какой же ты ущербный.

Serg_HIS
()
Ответ на: комментарий от anonymous_incognito

Возможно ты действительно запутываешь его

Просто CodePoint - это не что-то особенное, а номер символа в UTF-16

А теперь запутываешь ты. Вот цитата из The Unicode Standard Version 9.0 – Core Specification:

In the Unicode Standard, the codespace consists of the integers from 0 to 10FFFF₁₆, comprising 1,114,112 code points available for assigning the repertoire of abstract characters.

И при чём тут UTF-16? Это же просто ещё один из видов кодировок.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

От того что ты на педевикию людей посылаешь?

Лысый не смеши меня.

Serg_HIS
()
print("\u0438")

ТС, питон поддерживает хрюникод в виде code point-ов. Честно, не знаю, что там говорит стандарт, но по факту там utf-32 или utf-16, мне лень ковыряться, можешь сделать это сам, хотя, скорее всего, может зависеть от платформы и версии интерпретатора, так что полагаться на это не стоит.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 2)
Ответ на: комментарий от i-rinat

Глупости пишете. Юникод дурной из-за совместимости со старыми кодировками, чтобы ascii совместимо было и чтобы по категориям символы добавлять (привет utf-8 с его зарезервированными диапазонами). И вся путаница из-за этого. Вполне можно было пронумеровать все символы по порядку, а новые добавлять в конец, правда и на вывод писать не короткие числа, а достаточной длинны.

peregrine ★★★★★
()
Ответ на: комментарий от i-rinat

А теперь запутываешь ты. Вот цитата из The Unicode Standard Version 9.0 – Core Specification:

Как бы тебе сказать, ну формально да. CodePoints - это не символ, потому что могут быть ещё и модификаторы, которые конструируют букву, например, символы ударения в тексте сами по себе не выводятся (выводятся там где юникод некачественно поддержан), а изображается буква с символом ударения сверху. Тем не менее, для начала проще думать об Юникоде, как о таблице символов, аналогично ASCII, в которой каждый элемент называется CodePoint. И кодируется по-разному в разных представлениях Юникода.

И при чём тут UTF-16? Это же просто ещё один из видов кодировок.

Тут без поллитра не разобраться :-) Потому что UTF-16 - не просто вид кодировки, а усечённое подмножество полного юникода, кстати, utf-8 в этом смысле полнее.

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от peregrine

Частично согласен.

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

Например есть «И» он используется как в русском так и в украинском алфавите. Но притом этот символ один в кодировке и имеет разные значения в алфавитах языков.

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

Картинка не имеет отношения к содержанию. Можно было сделать это разными и, а как они пишутся пусть шрифтоклепатели парятся.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

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

Или это реализуется на уровне операционки?

Я не хвалюсь что всё знаю (я не идиот). Предполагаю, что в сам стандарт UTF как бэ и внесена поляризация на принадлежность символов к языкам.

Хотя это может делаться и на уровне операционки. Но это глупо.

Serg_HIS
()
Ответ на: комментарий от anonymous_incognito

Потому что UTF-16 - не просто вид кодировки, а усечённое подмножество полного юникода

В UTF-16 можно закодировать любой code point, разве нет? Почему это она усечённая?

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

В UTF-16 можно закодировать любой code point, разве нет? Почему это она усечённая?

Потому что есть UTF-32 и он не просто константнобайтный, в отличие от мультибайтного UTF-16, но в нём есть символы, отсутствующие в UTF-16.

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от anonymous_incognito

Кажется, я понял. Ты считаешь, что в UTF-16 всегда только два байта, так? Но там может быть либо два, либо четыре байта.

i-rinat ★★★★★
()
Ответ на: комментарий от Serg_HIS

Можно было изначально всю архитектуру делать правильно, но начиная с дремучих времен когда компы (и не совсем компы в современном понимании) страдали от нехватки памяти и поддерживали только английский пережитки остались и тянется куча геморроя, один из которых кодировки (utf-16 и utf-32 частично спасают во внутреннем представлении), но все равно ИМХО костыльно получилось. Завтра украинцы захотят отмазаться от русского языка и скажут, что их «А» надо писать с какой-нибудь волнистой линией, а не прямой. Примут закон и тут всему IT резко поплохеет. Маразм, конечно, но с историей буквы и их написание имеют свойство меняться. А и A разные буквы, а выглядят одинаково во многих шрифтах.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Завтра украинцы захотят отмазаться от русского языка и скажут, что их «А» надо писать с какой-нибудь волнистой линией

Я к тебе в частности и к другим россиянам на этом форуме очень хорошо отношусь. Давай не нужно.

Хотя в чём-то ты прав наверное...

Serg_HIS
()
Ответ на: комментарий от Serg_HIS

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

peregrine ★★★★★
()
Ответ на: комментарий от i-rinat

Ты считаешь, что в UTF-16 всегда только два байта, так? Но там может быть либо два, либо четыре байта.

Я как раз знаю, что правильный UTF-16 на самом деле имеет переменное число байт, в отличие от UTF-32. Почему и назвал его константнобайтным.

Но, кстати, похоже ошибался, полагая, что разная длина только за счёт модификаторов (вроде знаков ударения). Сейчас почитал и в общем, тут получается, что когда-то он действительно реализовывал только ucs-2.

В общем, если вкратце видимо так можно объяснить:

1) Есть Юникод, UCS. В нём есть CodePoint'ы, которые в первом приближении можно считать символами.

2) Есть схемы кодирования юникода. utf-8, utf-16, utf-32. И некоторые вариации.

3) Для большинства случаев достаточно двух байт utf-16, при этом их номер (значение) будет совпадать с CodePoint Юникода.

4) Значения utf-8 не совпадают с CodePoint за исключением ASCII-части.

5) Конкретно в Python запись \u в строке print подразумевает использование номера (CodePoint). Выводить коды «как есть» в консоль, надо в Питоне иначе (как именно не в курсе).

anonymous_incognito ★★★★★
()
Последнее исправление: anonymous_incognito (всего исправлений: 1)
Ответ на: комментарий от peregrine

Если тебе лично интересно (не в обиду) могу с тобой пообщаться на чисто украинском. Думаю ты многое не поймёшь.

Да я знаю украинский вполне не плохо. Примерно как и русский.

Но я не лингвист ни разу.

В Киеве как и большинство моих знакомых общаюсь на русском.

Serg_HIS
()
Ответ на: комментарий от peregrine

Ты и я встречаемся за пятой кружкой пЫва…

Ты говришь мне - «ну что у вас за язык такой, ну вот взять слово „незабаром“, так то перед баром или как?»

Я такой - «А вы говорите такое слово - сравни, та к это срав чы ни?»

Надеюсь посмеёмся :)

Serg_HIS
()
Ответ на: комментарий от anonymous_incognito

Ты ещё забыл про UTF-16LE/UTF-16BE, не упомянул про Byte-Order-Mark byte. А что? Раз уж начал эти детали тянуть, надо больше ада!

Выводить коды «как есть» в консоль, надо в Питоне иначе (как именно не в курсе).

sys.stdout.buffer.write(bytes("Буковки\n", "UTF-8"))
i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от Serg_HIS

могу с тобой пообщаться на чисто украинском. Думаю ты многое не поймёшь.

Тебя и на русском-то мало кто понимает...

i-rinat ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.