UTF-8 латино-1 проблемы с конвертацией, Python Django - PullRequest
3 голосов
/ 08 ноября 2008

хорошо, так что моя проблема в том, что у меня есть строка '\ 222 \ 222 \ 223 \ 225', которая хранится как latin-1 в БД. То, что я получаю от django (печатая его), является следующей строкой, «âââââ», которую я предполагаю, является UTF-преобразованием. Теперь мне нужно передать строку в функцию, которая выполняет эту операцию:

strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

Я получаю эту ошибку:

chr () arg вне диапазона (256)

Если я сначала пытаюсь закодировать строку как латиница-1, я получаю эту ошибку:

Кодек 'latin-1' не может кодировать символы в позиции 0-3: порядковый номер не в диапазоне (256)

Я прочитал кучу о том, как работает кодировка символов, и мне чего-то не хватает, потому что я просто не понимаю!

Ответы [ 3 ]

4 голосов
/ 08 ноября 2008

Ваша первая ошибка 'chr () arg not in range (256)', вероятно, означает, что вы недооценили значение, потому что chr не может принимать отрицательные числа. Я не знаю, что должен делать алгоритм шифрования, когда значение inputcounter + 33 больше, чем фактическое представление символов, вам придется проверить, что делать в этом случае.

О второй ошибке. Вы должны декодировать (), а не кодировать () обычный строковый объект, чтобы получить правильное представление ваших данных. encode () принимает объект Unicode (те, которые начинаются с u ') и генерирует обычную строку для вывода или записи в файл. decode () принимает строковый объект и генерирует объект Unicode с соответствующими точками кода. Это делается с помощью вызова unicode (), когда он генерируется из строкового объекта, вместо этого вы также можете вызвать a.decode ('latin-1').

>>> a = '\222\222\223\225'
>>> u = unicode(a,'latin-1')
>>> u
u'\x92\x92\x93\x95'
>>> print u.encode('utf-8')
ÂÂÂÂ
>>> print u.encode('utf-16')
ÿþ
>>> print u.encode('latin-1')

>>> for c in u:
...   print chr(ord(c) - 3 - 0 -30)
...
q
q
r
t
>>> for c in u:
...   print chr(ord(c) - 3 -200 -30)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: chr() arg not in range(256)
2 голосов
/ 08 ноября 2008

Как отмечает Винко, в Latin-1 или ISO 8859-1 нет печатных символов для восьмеричной строки, которую вы цитируете. Согласно моим примечаниям для 8859-1, «Элементы управления C1 (0x80 - 0x9F) взяты из ISO / IEC 6429: 1992. Он не определяет имена для 80, 81 или 99». Имена кодовых точек соответствуют спискам Винко:

\222 = 0x92 => PRIVATE USE TWO
\223 = 0x93 => SET TRANSMIT STATE
\225 = 0x95 => MESSAGE WAITING

Правильное кодирование UTF-8: Unicode, двоичный, шестнадцатеричный:

U+0092 = %11000010 %10010010 = 0xC2 0x92
U+0093 = %11000010 %10010011 = 0xC2 0x93
U+0095 = %11000010 %10010101 = 0xC2 0x95

МАЛЕНЬКОЕ ПИСЬМО А ЛАТИНЫ С CIRCUMFLEX - ISO 8859-1, код 0xE2 и, следовательно, Unicode U + 00E2; в UTF-8 это% 11000011% 10100010 или 0xC3 0xA2.

CENT SIGN - это ISO 8859-1, код 0xA2 и, следовательно, Unicode U + 00A2; в UTF-8 это% 11000011% 10000010 или 0xC3 0x82.

Итак, что бы вы ни видели, вы, похоже, не видите кодировку UTF-8 ISO 8859-1. Все остальное, кроме 5 байт, где вы должны увидеть 8.

Добавлена ​​: Предыдущая часть ответа посвящена утверждению «кодировка UTF-8», но игнорирует остальную часть вопроса, которая гласит:

Now I need to pass the string into a function that does this operation:

    strdecryptedPassword + chr(ord(c) - 3 - intCounter - 30)

I get this error: chr() arg not in range(256).  If I try to encode the
string as Latin-1 first I get this error: 'latin-1' codec can't encode
characters in position 0-3: ordinal not in range(256).

Вы на самом деле не показываете нам, как определяется intCounter, но если он будет постепенно увеличиваться для каждого символа, рано или поздно 'ord(c) - 3 - intCounter - 30' будет отрицательным (и, кстати, почему бы не объединить константы и использовать 'ord(c) - intCounter - 33'?), В этот момент chr() может пожаловаться. Вам нужно будет добавить 256, если значение отрицательное, или использовать операцию модуля, чтобы убедиться, что у вас есть положительное значение от 0 до 255, чтобы перейти к chr(). Поскольку мы не можем видеть, как увеличивается intCounter, мы не можем определить, будет ли он циклически изменяться от 0 до 255 или монотонно ли он увеличивается. Если последнее, то вам нужно выражение, такое как:

chr(mod(ord(c) - mod(intCounter, 255) + 479, 255))

где 256 - 33 = 223, конечно, и 479 = 256 + 223. Это гарантирует, что значение, переданное в chr(), положительно и находится в диапазоне 0..255 для любого входного символа c и любого значения intCounter (и, поскольку функция mod() никогда не получает отрицательный аргумент, она также работает независимо от того, как mod() ведет себя, когда ее аргументы отрицательны).

0 голосов
/ 08 ноября 2008

Ну, потому что он был зашифрован по какой-то ужасной схеме, которая просто изменяет ord () символа по какому-либо запросу, поэтому строка, выходящая из базы данных, была зашифрована, и это расшифровывает ее. То, что вы указали выше, похоже, не работает. В базе данных это latin-1, django преобразует его в unicode, но я не могу передать его функции как unicode, но когда я пытаюсь кодировать его в latin-1, я вижу эту ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...