Python3, проблемы с использованием кодирования / декодирования ctf-8 (в некоторых случаях) - PullRequest
0 голосов
/ 29 октября 2018

Итак, у меня проблемы с кодировкой Python3. У меня есть несколько байтов, которые я хочу работать как строки. (длинная история)

В двух словах, это работает

a = "\x85".encode()
print(a.decode())

Но это не

b = (0x85).to_bytes(1,"big")
print(b.decode())

UnicodeDecodeError: кодек utf-8 не может декодировать байт 0x85 в позиции 0: неверный стартовый байт

Я прочитал несколько статей на эту тему, но они настаивают на том, что «python3 не работает» или «вам не следует использовать строки для этого». Множество статей о Stackoverflow просто используют «обходные пути» (например, «используйте замену при ошибке» или «пользовательский utc-16»).

Может кто-нибудь сказать мне, в чем разница и почему функция работает, а вторая нет? Разве они не должны работать одинаково? Почему utf-8 не может декодировать байт со второй попытки?

1 Ответ

0 голосов
/ 29 октября 2018

В первом случае '\x85'.encode() кодирует кодовую точку Unicode U + 0085 в кодировке по умолчанию для Python 3 UTF-8. Таким образом, на выходе получается правильное двухбайтовое кодирование UTF-8 этой кодовой точки:

>>> '\x85'.encode()
b'\xc2\x85'

Затем работает декодирование, поскольку оно было правильно закодировано в UTF-8 для начала:

>>> b'\xc2\x85'.decode()
'\x85'

Второй случай - это сложный способ создания однобайтовой строки:

>>> (0x85).to_bytes(1,'big')
b'\x85'

Эта байтовая строка неправильно закодирована как UTF-8, поэтому она не может быть декодирована:

>>> b'\x85'.decode()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x85 in position 0: invalid start byte

Python 3 определенно не "сломан". Он четко отделяет байтовые данные от текста. Если у вас есть необработанные байты, работайте с ними как с байтами. Необработанные данные в Python 3 предназначены для работы в байтовых строках или байтовых массивах. Строки Unicode предназначены для текста. Декодировать байты в текст, чтобы манипулировать им, затем кодировать обратно в байты для сериализации в файл, сокет, базу данных и т. Д.

Если по какой-то причине вы чувствуете необходимость использовать строки Unicode для необработанных данных, первые 256 кодовых точек Unicode соответствуют кодеку latin1 для преобразования 1: 1 одного в другой.

>>> '\x85'.encode('latin1')
b'\x85'
>>> b'\x85'.decode('latin1')
'\x85'

Это часто используется для исправления ошибок программирования из-за кодирования / декодирования с неправильными кодировками.

...