2010-12-30 21 views
1

Ich benutze diese handliche Javascript-Funktion, um eine Base64-String zu dekodieren und ein Array im Gegenzug zu erhalten.Decode Base64 Daten als Array in Python

Dies ist die Zeichenfolge:

base64_decode_array('6gAAAOsAAADsAAAACAEAAAkBAAAKAQAAJgEAACcBAAAoAQAA') 

Dies ist, was zurückgegeben wird:

234,0,0,0,235,0,0,0,236,0,0,0,8,1,0,0,9,1,0,0,10,1,0,0,38,1,0,0,39,1,0,0,40,1,0,0 

Das Problem ist, verstehe ich nicht wirklich die JavaScript-Funktion:

var base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/'.split(""); 
var base64inv = {}; 
for (var i = 0; i < base64chars.length; i++) { 
    base64inv[base64chars[i]] = i; 
} 
function base64_decode_array (s) 
{ 
    // remove/ignore any characters not in the base64 characters list 
    // or the pad character -- particularly newlines 
    s = s.replace(new RegExp('[^'+base64chars.join("")+'=]', 'g'), ""); 

    // replace any incoming padding with a zero pad (the 'A' character is zero) 
    var p = (s.charAt(s.length-1) == '=' ? 
      (s.charAt(s.length-2) == '=' ? 'AA' : 'A') : ""); 

    var r = []; 

    s = s.substr(0, s.length - p.length) + p; 

    // increment over the length of this encrypted string, four characters at a time 
    for (var c = 0; c < s.length; c += 4) { 

    // each of these four characters represents a 6-bit index in the base64 characters list 
    // which, when concatenated, will give the 24-bit number for the original 3 characters 
    var n = (base64inv[s.charAt(c)] << 18) + (base64inv[s.charAt(c+1)] << 12) + 
      (base64inv[s.charAt(c+2)] << 6) + base64inv[s.charAt(c+3)]; 


    // split the 24-bit number into the original three 8-bit (ASCII) characters 
    r.push((n >>> 16) & 255); 
    r.push((n >>> 8) & 255); 
    r.push(n & 255); 


    } 
    // remove any zero pad that was added to make this a multiple of 24 bits 
    return r; 
} 

Was das ist Funktion dieser "< < <" und ">>>" Figuren. Oder gibt es eine Funktion wie diese für Python?

Antwort

10

Wen kümmert. Python hat einfachere Möglichkeiten, dasselbe zu tun.

[ord(c) for c in '6gAAAOsAAADsAAAACAEAAAkBAAAKAQAAJgEAACcBAAAoAQAA'.decode('base64')] 
+3

+1 für die "Who cares" zusätzlich zu der ausgezeichneten Antwort. –

+0

Nun, ich werde verdammt sein. Das ist wahnsinnig einfach. – skerit

5

In Python erwartete ich Sie würde nur die base64 module verwenden ...

... aber als Antwort auf Ihre Frage zu << und >>>:

  • << ist die linke Shift-Operator; das Ergebnis ist der erste Operand, der um die zweite Operandenanzahl von Bits nach links verschoben ist; zum Beispiel 5 << 2 ist 20, wie 5 ist 101 in binär und 20 ist 10100.
  • >>> ist der nicht-Zeichen-erweiterte Rechts-Shift-Operator; das Ergebnis ist der erste Operand rechts vom zweiten Operanden Anzahl von Bits verschoben ... mit dem Bit ganz links immer mit einem 0.
+0

+1 Für die Frage des OP über '<<' and '> Beantwortung >>'. – Brian

3

Warum nicht einfach gefüllt werden:

from binascii import a2b_base64, b2a_base64 
encoded_data = b2a_base64(some_string) 
decoded_string = a2b_base64(encoded_data) 

def base64_decode_array(string): 
    return [ord(c) for c in a2b_base64(string)] 
2

Just for fun/Vollständigkeit, werde ich die Javascript mehr buchstäblich übersetzen: :)

# No particular reason to make a list of chars here instead of a string. 
base64chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/' 
lookup = dict((c, i) for (i, c) in enumerate(base64chars)) 

def base64_decode_array(s): 
    # Filter out meaningless chars, especially newlines. No need for a regex. 
    s = ''.join(c for c in s if c in base64chars + '=') 

    # replace any incoming padding with a zero pad (the 'A' character is zero) 
    # Their way: 
    # p = ('AA' if s[-2] == '=' else 'A') if s[-1] == '=' else '' 
    # s = s[:len(s) - len(p)] + p 
    # My way (allows for more padding than that; 
    # '=' will only appear at the end anyway 
    s = s.replace('=', 'A') 

    r = [] 

    # Iterate over the string in blocks of 4 chars - an ugly hack 
    # though we are preserving the original code's assumption that the text length 
    # is a multiple of 4 (that's what the '=' padding is for) ;) 
    for a, b, c, d in zip(*([iter(s)] * 4)): 
    # Translate each letter in the quad into a 6-bit value and bit-shift them 
    # together into a 24-bit value 
    n = (lookup[a] << 18) + (lookup[b] << 12) + (lookup[c] << 6) + lookup[d] 

    # split the 24-bit number into the original three 8-bit (ASCII) characters 
    r += [(n >> 16) & 0xFF), (n >> 8) & 0xFF), (n & 0xFF)] 

    return r 
+0

Super! Ich denke, das "Vielfache von 4" Ding ist, weil, nachdem es decodiert ist, Sie immer noch alle 4 Zahlen bitweise verschieben müssen. Lustigerweise ist diese Codezeile in Python und Javascript fast identisch, abgesehen von den Variablennamen: (Python: 'tempTile = decodeData [i] | decodeData [i + 1] << 8 | decodeData [i + 2] < <16 | decodeData [i + 3] << 24' und Javascript: 'var tempTile = Quelle [i] | Quelle [i + 1] << 8 | Quelle [i + 2] << 16 | Quelle [i + 3 ] << 24; ') – skerit

+0

Ja, na ja, Mathe ist Mathe, und wenn man Dinge ansieht, schaut es sich an. –