Möchte man einen größeren Text z.B. mit dem ZIP-Algorithmus "eindampfen"
steht man zunächst vor dem Problem, dass dieser keine Sonderzeichen verarbeiten
kann. Die in Deutschland so beliebten Umlaute und andere Sonderzeichen sind
schlichtweg Tabu. Da hilft nur eine Kodierung und zwar mit dem sog. base64-Algorithmus,
auch MIME-Kodierung genannt. Entwickelt wurde dieser im Zuge ursprünglich, um
den Text von eMails zu vereinheitlichen, um Datenverluste durch unterschiedliche
Zeichensätze zu vermeiden. Die meisten eMail-Anhänge werden bis heute nach diesem
Verfahren codiert.
Grundlage der base64-Kodierung ist ein reduzierter Zeichensatz mit 64 Zeichen,
der in allen Zeichensätzen vorkommt:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
Diese 64 Zeichen entsprechen genau 6 Bits (64 = 26), daher wird
der Datenstrom eines Textes (z.B. "Test"), der 4 Zeichen (Bytes) mit 8 Bits
enthält, in 6-Bit-Häppchen zerlegt. Drei Bytes des Textes ergeben 4 Bytes der
Kodierung, d.h. die Byte-Länge des Textes muss durch drei teilbar sein. Ist
sie das nicht, d.h. die Aufteilung in 6er-Gruppen geht nicht auf (2 oder 4 Bits
fehlen) wird mit Nullen aufgefüllt.
Diese 6-Bitmustern werden anschließend Zeichen aus dem ASCII-Zeichensatz zugeordnet.
Die am Ende des neuen Strings aufgrund der angehängten Nullen entstandenen Buchstaben
'A' werden durch das Zeichen '=' ersetzt, dass in base64 als Füllzeichen gilt.
Obwohl jedes dieser ASCII-Zeichen nur 6 Bit darstellt, hat es jedoch weiterhin
einen Speicherbedarf von 8 Bit. Aus diesem Grunde ist ein base64-kodierter Text
auch 30% länger als der Quelltext.
Schema
| Zeichen |
T |
e |
s |
t |
[Füllz.] |
[Füllz.] |
[Füllz.] |
[Füllz.] |
| ASCII-Code |
84 |
101 |
115 |
116 |
|
|
|
|
| binär (8 Bit) |
01010100 |
01100101 |
01110011 |
01110100 |
00000000 |
00000000 |
|
|
| 6 Bit-Gruppe |
010101 |
000110
|
010101
|
110011 |
011101 |
000000 |
000000 |
000000 |
| dezimal |
86 |
71 |
86 |
90 |
100 |
0 |
0 |
0 |
| Zeichen |
V |
G |
V |
z |
d |
= |
= |
= |
Kodieren
Public Function EncodeBase64(strInput As String) As String
Dim arrChars64() As Byte
Dim arrInput() As Byte
Dim arrOutput() As Byte
Dim arrByte(3) As Integer
Dim arrChar(4) As Integer
Dim intLen As Integer
Dim intDelta As Integer
Dim i As Long
Dim j As Long
Const cstrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
'Zeichentabelle in Byte-Array ablegen
arrChars64() = StrConv(cstrBase64, vbFromUnicode)
'Länge ermitteln und prüfen
intLen = Len(strInput)
If intLen = 0 Then Exit Function
'Input in Byte-Array ablegen
arrInput() = StrConv(strInput, vbFromUnicode)
'Wenn Input nicht glatt durch 3 teilbar...
intDelta = intLen Mod 3
If intDelta > 0 Then
'...Input-Array auf die nächste durch 3 teilbare Zahl erweitern
intLen = ((intLen \ 3) + 1) * 3
ReDim Preserve arrInput(intLen - 1)
End If
'Ergebnis-Array ist im 1/3 länger als das Input-Array
ReDim arrOutput((4 * (intLen / 3)) - 1)
'Schleife über Input-Array in 3er-Schrittweite...
For i = 0 To intLen - 1 Step 3
'3 Byte lesen
arrByte(1) = arrInput(i)
arrByte(2) = arrInput(i + 1)
arrByte(3) = arrInput(i + 2)
'6 Bit extrahieren
arrChar(1) = Int(arrByte(1) / 4)
arrChar(2) = (arrByte(1) And 3) * 16 + Int(arrByte(2) / 16)
arrChar(3) = (arrByte(2) And 15) * 4 + Int(arrByte(3) / 64)
arrChar(4) = arrByte(3) And 63
'Laufvariable um 1/3 erhöhen
j = (i \ 3) * 4
'6-Bit-Wert im Output-Array durch Base64-Array-Wert ersetzen
arrOutput(j) = arrChars64(arrChar(1))
arrOutput(j + 1) = arrChars64(arrChar(2))
arrOutput(j + 2) = arrChars64(arrChar(3))
arrOutput(j + 3) = arrChars64(arrChar(4))
Next
'Überzählige Bytes im Output mit Füll-Byte "=" belegen
Select Case intDelta
Case 1 '2 Bit
arrOutput(UBound(arrOutput)) = 61
arrOutput(UBound(arrOutput) - 1) = 61
Case 2 '4 Bit
arrOutput(UBound(arrOutput)) = 61
End Select
'Output-Array in String umwandeln
EncodeBase64 = StrConv(arrOutput, vbUnicode)
End Function
Dekodieren
Das dekodieren funktioniert genau andersherum wie das Kodieren, wobei alle
nicht in der base64-Zeichentabelle enthaltenen Zeichen ignoriert werden.
Public Function DecodeBase64(strInput As String) As String
Dim arrChars64() As Byte
Dim arrChars64Rev() As Byte
Dim arrInput() As Byte
Dim arrOutput() As Byte
Dim arrChar(4) As Integer
Dim intLen As Long
Dim intDelta As Long
Dim i As Long
Dim j As Long
Const Base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
'Zeichentabelle in Byte-Array ablegen
arrChars64() = StrConv(Base64, vbFromUnicode)
'Hilfs-Array für Umkehrtabelle dimensionieren
ReDim arrChars64Rev(255)
'Zeichentabelle in Hilfs-Array überkreuz übertragen
For i = 0 To UBound(arrChars64)
arrChars64Rev(arrChars64(i)) = i
Next i
'Länge ermitteln und prüfen
intLen = Len(strInput)
If intLen = 0 Then Exit Function
'Wenn Input nicht glatt durch 4 teilbar...
intDelta = intLen Mod 4
If intDelta > 0 Then
'... Input-Array mit Nullen auffüllen
strInput = strInput + String$(4 - intDelta, 0)
intLen = Len(strInput)
End If
'Input in Byte-Array umgewandeln
arrInput() = StrConv(strInput, vbFromUnicode)
'Output-Array 1/3 kleiner als das Input-Array dimensionieren
ReDim arrOutput(((intLen + 1) / 4) * 3)
'Schleife über Input-Array in 4er-Schrittweite...
For i = 0 To UBound(arrInput) Step 4
'4 Byte lesen
arrChar(1) = arrChars64Rev(arrInput(i))
arrChar(2) = arrChars64Rev(arrInput(i + 1))
arrChar(3) = arrChars64Rev(arrInput(i + 2))
arrChar(4) = arrChars64Rev(arrInput(i + 3))
'in 8 Bit umwandeln
arrOutput(j) = ((arrChar(1) * 4 + Int(arrChar(2) / 16)) And 255)
j = j + 1
arrOutput(j) = ((arrChar(2) * 16 + Int(arrChar(3) / 4)) And 255)
j = j + 1
arrOutput(j) = ((arrChar(3) * 64 + arrChar(4)) And 255)
j = j + 1
Next
'Byte-Array in String umwandeln und NullChars entfernen
DecodeBase64 = Replace(StrConv(arrOutput, vbUnicode), vbNullChar, "")
End Function
Wer das base64-Verfahren etwas näher betrachten möchte, dem sei die Seite
von
Arndt Brünner empfohlen, der sich neben vielen anderen mathematischen Problemen
auch mit dieser Kodierung beschäftigt.
Weiterhin zu empfehlen ist eine Seite aus dem HTML-Standardwerk
SelfHTML. Dort findet man auch auch eine sehr gute JavaScript-Implementierung.
Downloads
modBase64.zip