2010-07-01 79 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咸菜。

相关问题