UTF-8 latin-1转换问题,python django

时间:2008-11-08 04:24:45

标签: python django utf-8 character-encoding

好吧所以我的问题是我有字符串'\ 222 \ 222 \ 223 \ 225',它在数据库中存储为latin-1。我从django(通过打印它)获得的是以下字符串,''我假设是它的UTF转换。现在我需要将字符串传递给一个函数 做这个操作:

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

我收到此错误:

  

chr()arg不在范围(256)

如果我首先尝试将字符串编码为latin-1,我会收到此错误:

  

'latin-1'编解码器无法编码位置0-3中的字符:序数不是   在范围(256)

我已经阅读了很多关于字符编码如何工作的内容,而且我还缺少一些东西,因为我只是没有得到它!

3 个答案:

答案 0 :(得分:4)

你的第一个错误'chr()arg不在范围(256)'可能意味着你已经使该值下溢,因为chr不能取负数。当输入计数器+ 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)

答案 1 :(得分:2)

正如Vinko所说,Latin-1或ISO 8859-1没有您引用的八进制字符串的可打印字符。根据我对8859-1的说明,“C1 Controls(0x80 - 0x9F)来自ISO / IEC 6429:1992。它没有定义80,81或99”的名称。代码点名称如Vinko列出的那样:

\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的LATIN小写字母A是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。

所以,无论你看到什么,你似乎都没有看到ISO 8859-1的UTF-8编码。除此之外,你只能看到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()的值为正,对于任何输入字符c和任何值,在0..255范围内intCounter(并且,因为mod()函数永远不会得到否定参数,所以无论mod()在其参数为负时如何表现,它也都有效。

答案 2 :(得分:0)

好吧,因为它是用一些可怕的方案加密的,只是通过某些请求改变了字符的ord(),所以来自数据库的字符串已被加密,这会解密它。你上面提供的东西似乎不起作用。在数据库中它是latin-1,django将其转换为unicode,但我无法将其作为unicode传递给函数,但是当我尝试将其编码为latin-1时,我看到了该错误。