2012-09-27 61 views
3

众所周知,计算机使用数字。我现在正在输入这个文本,服务器发出一个数字,当你想读取它时,你会从服务器获取文本。Python3将Unicode字符串转换为int表示形式

我该怎么做我自己?

我想用我自己的算法加密一些东西,我的算法对整数工作正常,但现在我想加密一个字符串,我不知道如何将Unicode字符串转换为整数,反之亦然。

我正在使用Python 3.有没有人知道我的问题的优雅解决方案?

+3

*“我想用我自己的算法加密某些东西” - 为什么? – Amber

+0

欢迎来到Stack Overflow!我们鼓励你[研究你的问题](http://stackoverflow.com/questions/how-to-ask)。如果你已经[尝试了某些东西](http://whathaveyoutried.com/),请将其添加到问题中 - 如果没有,请先研究并尝试您的问题,然后再回来。 – 2012-09-27 16:14:13

+0

,因为我想学习语言,我只是在玩一点点,我试图找到一个解决所有upcomming问题。在这个问题上,我没有找到任何解决方案。我不会发布我的algorthm,因为我知道这不安全,但正如我所说,我只是在玩一点点。 @tichodrama:我发现没有关于这个问题的任何问题 – Emerald

回答

9

您正在寻找ord() function,我想:

>>> ord('a') 
97 
>>> ord('\u00c2') 
192 

要一整套转换的字符,使用列表理解:

>>> [ord(c) for c in 'Hello World!'] 
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33] 

它的倒数就是chr() function

>>> chr(97) 
'a' 
>>> chr(193) 
'Á' 
+0

我可以做到这一点与整体串?(一个字符串 - >一个整数) – Emerald

+0

@Emerald:这个整数意味着什么?您可以将每个*字符*转换为整数;我已经更新了我的答案,以显示如何为整个字符串做这件事。将该字符串转换为*一个*号码没有多大意义。 –

+0

我认为发送一个整数到我的算法比数百个更快,但我认为你的解决方案是最好的。非常感谢! – Emerald

0

这将每个字符转换为一个数字...

s="hello \u2020" 
print [ord(c) for c in s] 
+0

我可以用整串吗? (一个字符串 - >一个整数) – Emerald

+0

正如Martijn在他的回答中所说的那样,把字符串作为一个整体转换并没有多大意义。并且加密例程应该使用一串数字 - 例如[hashlib.update](http://docs.python.org/library/hashlib.html)。 – spiralx

1

大厦由马亭皮特斯给出的解决方案,可以让你的字符串数量庞大,有什么Python 3中可以处理得很好,因为它是整数类型是任意大的(即不是“电脑是如何工作的”,看到我的评论你的问题)。

鉴于字符数字代码清单:

>>> a = [ord(c) for c in 'Hello World!'] 
>>> print(a) 
[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33] 

,知道,维基百科的页面上Unicode,最大的Unicode字符数是10FFFF(十六进制),你可以这样做:

def numfy(s): 
    number = 0 
    for e in [ord(c) for c in s]: 
     number = (number * 0x110000) + e 
    return number 

def denumfy(number): 
    l = [] 
    while(number != 0): 
     l.append(chr(number % 0x110000)) 
     number = number // 0x110000 
    return ''.join(reversed(l)) 

因此:

>>> a = numfy("Hello, World, عالَم, ދުނިޔެ, जगत, 世界") 
>>> a 
31611336900126021[...]08666956 
>>> denumfy(a) 
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界' 

凡本0x110000(从10FFFF + 1)是不同预见的Unicode字符数(1114112,十进制)。如果你确定你只使用英文字母,那么你可以在这里使用128,如果你使用一些带有重音符号的拉丁语,那么使用256是安全的。无论哪种方式你的号码会小得多,但它将无法代表每个Unicode字符。

7

将Unicode字符串转换为的常用方法是将其转换为字节序列。 Unicode字符是纯粹的抽象,每个字符都有自己的编号;但是,还有更多方法可将数字转换为字节流。也许最通用的方式是将字符串编码为UTF-8编码。您可以选择许多方法从中获取整数。这里是一个(我借用Ivella漂亮的字符串 - 我希望没有坏的话是内部:):

Python 3.2.1 (default, Jul 10 2011, 20:02:51) [MSC v.1500 64 bit (AMD64)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> s = "Hello, World, عالَم, ދުނިޔެ, जगत, 世界" 
>>> b = s.encode('utf-8') 
>>> b 
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c' 

现在我们这里有从128到255的数字的那些显示为字节序列十六进制编码转义序列。我们将所有字节转换为它们的十六进制字节作为字节串。

>>> import binascii 
>>> h = binascii.hexlify(b) 
>>> h 
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c' 

而且我们可以把它看作以十六进制符号写成的大数字(如文本)。 int允许我们将其转换为抽象数字 - 在打印时 - 通常更多地转换为十进制符号。现在

>>> i = int(h, 16) 
>>> i 
52620351230730152682202055464811384749235956796562762198329268116226267262806875102376740945811764490696968801603738907493997296927348108 

你可以将它存储为一个数字,它加密(虽然它是比较平常字节更早的序列加密),后来将其转换回整数。要小心,没有很多语言(可能没有数据库)能够使用这些大整数。

让我们回到原始字符串。首先将其转换为十六进制表示(字符串)。

>>> h2 = hex(i) 
>>> h2 
'0x48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c' 
>>> h3 = h2[2:] # remove the 0x from the beginning 
>>> h3 
'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c' 
>>> type(h3) 
<class 'str'> 

我们不得不删除0x,因为它只是说,其余的是代表人数的十六进制字符。请注意0​​是str类型。就像我们在Python 3中一样(请参见上方),str表示Unicode字符串。下一步是将六个数字对转换回字节。试试吧unhexlify()

>>> binascii.unhexlify(h3) 
Traceback (most recent call last): 
    File "<pyshell#16>", line 1, in <module> 
    binascii.unhexlify(h3) 
TypeError: 'str' does not support the buffer interface 

哎呀!它只接受字节串​​。然后,将Unicode中的每个六进制数字编码为bytestring中的六进制数字。要走的路是编码;然而,编码为ASCII是微不足道的。

>>> b2 = h3.encode('ascii') # character by character; subset of ascii only 
>>> b2 
b'48656c6c6f2c20576f726c642c20d8b9d8a7d984d98ed9852c20de8bdeaade82dea8de94deac2c20e0a49ce0a497e0a4a42c20e4b896e7958c' 
>>> b3 = binascii.unhexlify(b2) 
>>> b3 
b'Hello, World, \xd8\xb9\xd8\xa7\xd9\x84\xd9\x8e\xd9\x85, \xde\x8b\xde\xaa\xde\x82\xde\xa8\xde\x94\xde\xac, \xe0\xa4\x9c\xe0\xa4\x97\xe0\xa4\xa4, \xe4\xb8\x96\xe7\x95\x8c' 

现在我们有类似的字符串,跟第一个.encode('utf-8')之后相似。让我们使用逆操作 - 从UTF-8解码。我们应该得到和我们一样的Unicode字符串。

>>> s2 = b3.decode('utf-8') 
>>> s2 
'Hello, World, عالَم, ދުނިޔެ, जगत, 世界' 
>>> s == s2 # is the original equal to the result? 
True 

:)

4

从python的文档:

binascii module包含了许多方法来 二进制和各种ASCII编码的二进制表示法之间的转换。

例如,你可以使用binascii.hexlify获得二进制串“LOL”的十六进制表示,并将其转化为一个整数通过int内置函数:

>>> binascii.hexlify(b"LOL") 
b'4c4f4c' 
>>> int(binascii.hexlify(b"LOL"), 16) 
5001036 

由于您需要将此应用于unicode字符串,您首先需要将它们编码为二进制字符串。您可以使用方法str.encode达到此目的:

>>> int(binascii.hexlify("fiŝaĵo".encode("utf-8")), 16) 
7379646744164087151 

就是这样。

反之亦然,您需要反转每一步。首先把整数的十六进制表示的二进制字符串(你可以用format(int, "x")去,然后对其进行编码),转向以ASCII十六进制与binascii.unhexlify终于解码为UTF-8:

>>> binascii.unhexlify(format(7379646744164087151, "x").encode("utf-8")).decode("utf-8") 
'fiŝaĵo' 

这是一个步进一步一步的解释,如果你确实会使用这些设施,那么以功能的形式安排它们是一个好主意。

+0

老兄我非常爱你,为什么地球上不是这个答案? – user3753342

相关问题