2012-09-27 95 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

相關問題