2008-11-08 4 views
3

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

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

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

chr() arg not in range(256)

Если я пытаюсь кодировать строку как Latin-1 первый я получаю это ошибка:

'latin-1' codec can't encode characters in position 0-3: ordinal not in range(256)

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

ответ

4

Ваша первая ошибка «chr() arg не в диапазоне (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) 
0

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

+0

Пожалуйста, введите фактический код с реальным примером строки, потому что u '\ 222 \ 222 \ 223 \ 225'.encode (' latin-1 ') работает для меня – 2008-11-08 05:47:40

+0

и для c в u' \ 222 \ 222 \ 223 \ 225 ': print chr (ord (c) - 33) также работает. Он также работает со строковыми объектами. – 2008-11-08 05:49:09

2

Как отмечает Vinko, Latin-1 или ISO 8859-1 не имеют печатных символов для восьмеричной строки, которую вы цитируете. Согласно моим заметкам для 8859-1, «C1 Controls (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 

Латинского МАЛЫЙ буква А С циркумфлексом является 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(). Поскольку мы не можем видеть, как инкремент инкрементируется, мы не можем определить, имеет ли он цикл от 0 до 255 или монотонно увеличивается. Если последнее, то вам необходимо выражение таких как:

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

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