2010-07-01 145 views
1

我編寫了這個python代碼,試圖將對象轉換爲一個零的字符串,但解碼失敗,因爲數據不能取消。這是代碼:Python編碼函數無法解碼

def encode(obj): 
    'convert an object to ones and zeros' 
    def tobin(str): 
     rstr = '' 
     for f in str: 
      if f == "0": rstr += "0000" 
      elif f == "1": rstr += "0001" 
      elif f == "2": rstr += "0010" 
      elif f == "3": rstr += "0100" 
      elif f == "4": rstr += "1000" 
      elif f == "5": rstr += "1001" 
      elif f == "6": rstr += "1010" 
      elif f == "7": rstr += "1100" 
      elif f == "8": rstr += "1101" 
      elif f == "9": rstr += "1110" 
      else: rstr += f 
     return rstr 
    import pickle, StringIO 
    f = StringIO.StringIO() 
    pickle.dump(obj, f) 
    data = f.getvalue() 
    import base64 
    return tobin(base64.b16encode(base64.b16encode(data))) 
def decode(data): 
    def unbin(data): 
     rstr = '' 
     for f in data: 
      if f == "0000": rstr += "0" 
      elif f == "0001": rstr += "1" 
      elif f == "0010": rstr += "2" 
      elif f == "0100": rstr += "3" 
      elif f == "1000": rstr += "4" 
      elif f == "1001": rstr += "5" 
      elif f == "1010": rstr += "6" 
      elif f == "1100": rstr += "7" 
      elif f == "1101": rstr += "8" 
      elif f == "1110": rstr += "9" 
     return rstr 
    import base64 
    ndata = base64.b16decode(base64.b16decode(unbin(data))) 
    import pickle, StringIO 
    f = StringIO.StringIO(ndata) 
    obj = pickle.load(f) 
    return obj 
+6

你知道Python有內置的'bin()'函數嗎? – 2010-07-01 19:12:39

+0

他的二進制字符串轉換有些損壞(例如0100 <-> 3) – 2010-07-01 19:21:34

+0

@Tim Pietzcker:'tobin'沒有執行二進制轉換。 – jdmichal 2010-07-01 19:22:13

回答

2

我覺得有幾個問題,但一個是,當你解碼,你需要像你目前在您完成的4個字符組迭代unbin()函數,而不是單個字符這樣做。

+0

謝謝。我修復它,所以它遍歷4個字符,現在它工作正常。 – JoeBob 2010-07-01 19:37:04

0

binunbin功能是不是彼此的逆,因爲bin有那樣只會把字符逐字到輸出else子句,但unbin沒有else子句將它們傳回。

+0

其他應該做出拋出異常,因爲它是由設計無法訪問 - base64.b16encode(base64.b16encode())確保只有數字 – 2010-07-01 22:28:51

+0

最後我看了,b16encode使用0-9和A-F。 – 2010-07-01 22:38:34

1

我想我對你有更好的解決方案。這應該是更安全的,因爲它「加密」的一切,不只是數字:

MAGIC = 0x15 # CHOOSE ANY TWO HEX DIGITS YOU LIKE 

# THANKS TO NAS BANOV FOR THE FOLLOWING: 
unbin = tobin = lambda s: ''.join(chr(ord(c)^MAGIC) for c in s) 
+0

優化'unbin = tobin'而不是'def unbin' :-D – 2010-07-01 21:36:45

+0

@Nas Banov我想知道你是否可以做到這一點。我根本不使用python,幾乎只是從提問者那裏複製語法。 :) – jdmichal 2010-07-01 21:56:07

+0

是的,你可以。但是現在我注意到了代碼中的某些東西 - 你不能在字符串上使用'^'。因爲我們越來越糾結,這裏是替代建議:'unbin = tobin = lambda s:''.join(chr(ord(c)^ MAGIC)for c in s)' – 2010-07-01 22:26:01

0

順便說一句... base64.b16encode(base64.b16encode(data))相當於data.encode('hex').encode('hex')。並且有更簡單和更快速的方法來進行映射,這種編碼的整個思想雖然表面上看起來很複雜,但並不是很好。首先,它並沒有做太多的加密,因爲從十六進制轉儲每個數字被始終匹配的0和1的相同的8長度的字符串:

>>> hexd = 'ABCDEF' 
>>> s = hexd.encode('hex') 
>>> s 
'30313233343536373839414243444546' 
>>> s=''.join(["0000","0001","0010","0100","1000","1001","1010","1100","1101","1110"][int(c)] for c in s) 
>>> s 
'01000000010000010100001001000100010010000100100101001010010011000100110101001110100000011000001010000100100010001000100110001010' 
>>> for i in range(0,len(s),8): 
...  print hexd[i/8], s[i:i+8], chr(int(s[i:i+8],2)) 
... 
0 01000000 @ 
1 01000001 A 
2 01000010 B 
3 01000100 D 
4 01001000 H 
5 01001001 I 
6 01001010 J 
7 01001100 L 
8 01001101 M 
9 01001110 N 
A 10000001 
B 10000010 ‚ 
C 10000100 „ 
D 10001000 ˆ 
E 10001001 ‰ 
F 10001010 Š 

其次,炸燬醃製對象的大小16次!即使你通過將'0'和'1'的每8位轉換爲字節(比如chr(int(encoded[i:i+8],2)))來打包,仍然是2x鹹菜。

相關問題