2010-07-01 7 views
1

오브젝트를 1과 0의 문자열로 변환하려고이 파이썬 코드를 작성했지만 데이터를 파이핑 해제 할 수 없기 때문에 디코딩이 실패합니다. 이 코드입니다 : 나는 몇 가지 문제가 있다고 생각파이썬 인코딩 함수를 디코딩 할 수 없습니다.

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

파이썬에는'bin()'함수가 내장되어 있습니다. –

+0

바이너리 문자열 변환이 다소 엉망입니다 (예 : 0100 <-> 3) –

+0

@Tim Pietzcker :'tobin'은 이진 변환을 수행하지 않습니다. – jdmichal

답변

2

, 그러나 사람은 당신이 디코딩 할 때, 당신은 당신이 현재처럼 4 개 문자의 그룹을 통해 unbin() 함수 하나없는 문자를 반복 할 필요가 있다는 것입니다 하기. bin 그냥 출력으로 그대로 문자를 두는 다른 조항을 가지고 있기 때문에

+0

감사합니다. 나는 그것을 고정 시켜서 4 문자를 반복하고 이제는 잘 동작한다. – JoeBob

0

귀하의 binunbin 기능은 서로 역함수가 아니라 그들을 다시 통과 할 다른 절은 unbin이 없습니다.

+0

base64.b16encode (base64.b16encode())는 숫자가 0이되도록 보장합니다. –

+0

마지막으로 보았을 때 b16encode는 0-9와 A-F를 사용했습니다. –

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

'def unbin' 대신에'unbin = tobin'을 최적화했습니다 :-D –

+0

@Nas Banov 당신이 그렇게 할 수 있는지 궁금합니다. 나는 파이썬을 전혀 사용하지 않고 단지 구도자로부터 구문을 복사하고 있었다. :) – jdmichal

+0

그래, 할 수있어. 하지만 이제는 코드에서 뭔가를 알아 차릴 수 있습니다. 문자열에'^'을 사용할 수 없습니다. 그리고 우리가 변태를 겪고 있기 때문에, 대체는 다음과 같이 제안합니다 :'unbin = tobin = lambda s : ''.join (chr (ord (c)^MAGIC) for C)' –

0

... base64.b16encode(base64.b16encode(data))data.encode('hex').encode('hex')에 해당 : 이것은 모든 아니라 숫자를 "암호화"때문에 훨씬 더 안전합니다. 그리고이 인코딩의

def tobin(numStr): 
    return ''.join(("0000","0001","0010","0100","1000","1001","1010","1100","1101","1110")[int(c)] for c in numStr) 

전체 아이디어는 표면에 복잡한 보이는 동안, 아주 좋지 않다, 매핑을 할 수있는 간단하고 빠른 방법이있다. 헥스 덤프에서 각 숫자는 0과 1의 같은 팔 길이 문자열에 항상 일치됩니다 이후 첫째, 암호화의 많은 일을하지 않습니다 둘째

>>> 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입니다.

관련 문제