Last active
March 26, 2018 01:39
-
-
Save w495/f4665140dc545d9dcc9429e11b486795 to your computer and use it in GitHub Desktop.
Почему «Билл Гейтс» превратился в `«Р‘илл Гейтс»` или проблема с кодировками cp1251 и utf8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## РОДНОЕ ПРЕДСТАВЛЕНИЕ UTF8-СТРОКИ: | |
>>> [ord(i) for i in 'Бил Гейтс'] | |
[208, 145, 208, 184, 208, 187, | |
32, | |
208, 147, 208, 181, 208, 185, 209, 130, 209, 129] | |
# Что тут происходит: | |
# * Я перебираю все символы строки через цикл FOR. | |
# * Вычисляю положение каждого символа | |
# в таблице ASCII через функцию `ord` (от слова `order`). | |
# * Обрати внимание: | |
# * все числа от 0 до 256. | |
# * число символов и чисел не совпадает: | |
# * каждый символ кириллицы представлен двумя числами; | |
# * 208 и 209 — префиксы характерные для кириллицы. | |
# * 32 — это пробел. Он представлен одним числом. | |
# Т.к. пробел и в Африке пробел. | |
# ПРЕДСТАВЛЕНИЕ UTF8-СТРОКИ В UNICODE | |
>>> [ord(i) for i in unicode('Бил Гейтс', 'utf8')] | |
[1041, 1080, 1083, | |
32, | |
1043, 1077, 1081, 1090, 1089] | |
# Что тут происходит: | |
# * Тоже самое, что и ранее. | |
# * Только предварительно привожу строку к Unicode. | |
# * Обрати внимание: Есть числа больше чем 256, | |
# зато число символов и чисел совпадает. | |
# * 32 — это пробел. | |
# Важный момент — минимальная единица представления информации — байты. | |
# В Unicode строки представлены списками чисел, а не байт. | |
# Потому на современной технике нет способа вывести на экран Unicode-строку. | |
# Её придется преобразовать во одно из байтовых представлений. | |
# Само по себе преобразование к UTF-8 — не простая задача. | |
# Наибоее примитивные пример выглядит так: | |
# https://github.com/w495/mai-workshops-2013/blob/ce9993c943f8a83d5cac9cd3b93c8bd589ae80f0/ws21/fls/fls.py#L246 | |
# UTF-8 — это общепринятое представление Unicode строк в Интернете. | |
# Многие ОС, (Linux, Unix, Mac OS и пр.) стали использовать Unicode + UTF-8. | |
# Потому там нет проблем отображения. И в самой OC и в Интернете одна | |
# и та же кодировка. Однако, в некоторых случаях проблемы | |
# с кодировками остаются актуальными. | |
# Например, не понятно, как считать длину строки в UTF8. | |
# Для правильного вычисления постоянно приходится переводить в Unicode. | |
>>> len('Бил Гейтс') # Длина строки в UTF-8 | |
17 | |
>>> len(unicode('Бил Гейтс', 'utf8')) # Длина строки в Unicode | |
9 | |
# На данный момент предлагается спрятать эту проблему на уровень ОС и | |
# интерпретаторов языков программирования, чтобы даже программисты | |
# об этом не задумывались. Но чудо — до сих пор не произошло. | |
# На дворе 2018. Но с 1985 почти ничего не изменилось. | |
# ПРЕДСТАВЛЕНИЕ ЭТО CP1251-СТРОКИ В UNICODE | |
>>> [ord(i) for i in unicode('Бил Гейтс', 'cp1251')] | |
[1056, 8216, 1056, 1105, 1056, 187, | |
32, | |
1056, 8220, 1056, 181, 1056, 8470, 1057, 8218, 1057, 1027] | |
# Что тут происходит: | |
# * Тоже самое, что и ранее. | |
# * Только к Unicode приводится строка из cp1251. | |
# * Из-за ошибочной интерпретации однобайтовая кодировка (cp1251) | |
# начинает восприниматься как многобайтовая. | |
# Потому каждому символу ставится в соответствие 2 числа. | |
# * 32 — это пробел. | |
# ПРЕДСТАВЛЕНИЕ ЭТО CP1251-СТРОКИ В UTF8 | |
>>> [ord(i) for i in unicode('Бил Гейтс', 'cp1251').encode('utf8')] | |
[208, 160, 226, 128, 152, 208, 160, 209, 145, 208, 160, 194, 187, | |
32, | |
208, 160, 226, 128, 156, 208, 160, 194, 181, 208, 160, 226, 132, | |
150, 208, 161, 226, 128, 154, 208, 161, 208, 131] | |
# Что тут происходит: | |
# * Тоже самое, что и ранее. | |
# * Все числа большие 256 разбиваются на 2 числа меньшие 256. | |
# * 32 — это пробел. | |
# * При попыте вывести это на экран получаем «Р‘РёР» Гейтс» |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Навеяно картинкой:
И ещё одной: