Скажем, у меня есть строка в Python:
>>> s = 'python'
>>> len(s)
6
Теперь я encode
эта строка выглядит так:
>>> b = s.encode('utf-8')
>>> b16 = s.encode('utf-16')
>>> b32 = s.encode('utf-32')
То, что я получаю из вышеперечисленных операций, - это массив байтов, то есть b
, b16
и b32
- это просто массивы байтов (каждый байт, конечно, 8-битный).
Но мы закодировали строку. Итак, что это значит? Как мы присоединяем понятие "кодирования" к необработанному массиву байтов?
Ответ заключается в том, что каждый из этих массивов байтов генерируется определенным образом. Посмотрите на эти массивы:
>>> [hex(x) for x in b]
['0x70', '0x79', '0x74', '0x68', '0x6f', '0x6e']
>>> len(b)
6
Этот массив указывает, что для каждого символа мы имеем один байт (потому что все символы падают ниже 127). Следовательно, можно сказать, что "кодирование" строки в "utf-8" собирает каждый символ, соответствующий кодовой точке, и помещает его в массив. Если точка кода не может поместиться в один байт, то utf-8 потребляет два байта. Следовательно, utf-8 потребляет наименьшее количество байтов.
>>> [hex(x) for x in b16]
['0xff', '0xfe', '0x70', '0x0', '0x79', '0x0', '0x74', '0x0', '0x68', '0x0', '0x6f', '0x0', '0x6e', '0x0']
>>> len(b16)
14 # (2 + 6*2)
Здесь мы видим, что "encoding to utf-16" сначала помещает двухбайтную BOM (FF FE
) в массив байтов, а затем для каждого символа он помещает два байта в массив. (В нашем случае второй байт всегда равен нулю)
>>> [hex(x) for x in b32]
['0xff', '0xfe', '0x0', '0x0', '0x70', '0x0', '0x0', '0x0', '0x79', '0x0', '0x0', '0x0', '0x74', '0x0', '0x0', '0x0', '0x68', '0x0', '0x0', '0x0', '0x6f', '0x0', '0x0', '0x0', '0x6e', '0x0', '0x0', '0x0']
>>> len(b32)
28 # (2+ 6*4 + 2)
В случае "кодирования в utf-32" мы сначала помещаем спецификацию, затем для каждого символа мы помещаем четыре байта и, наконец, ставим два байта в массив.
Следовательно, можно сказать, что "процесс кодирования" собирает 1 2 или 4 байта (в зависимости от имени кодировки) для каждого символа в строке и добавляет и добавляет к ним больше байтов для создания конечного массива результатов байтов.
Теперь, мои вопросы:
- Насколько я понимаю процесс кодирования или я что-то упускаю?
- Мы видим, что представление памяти переменных
b
,b16
иb32
на самом деле является списком байтов. Каково представление памяти в строке? Точно что хранится в памяти для строки? - Мы знаем, что когда мы делаем
encode()
, каждая символьная соответствующая кодовая точка собирается (кодовая точка, соответствующая имени кодировки) и помещается в массив или байты. Что именно происходит, когда мы делаемdecode()
? - Мы можем видеть, что в utf-16 и utf-32 добавлена спецификация, но почему в кодировке utf-32 добавляются два нулевых байта?