Base64-Kodierung in Visual Basic: Ein vollständiger Leitfaden
Hier ist ein Problem, auf das Visual-Basic-Entwickler seit fünfundzwanzig Jahren treffen: Sie haben ein JPEG, einen Binär-Blob, eine Lizenzdatei oder einen völlig gewöhnlichen Satz, und der Kanal vor Ihnen akzeptiert nur Text. Ein JSON-Feld, eine Umgebungsvariable, ein E-Mail-Anhang, eine URL, eine Konfigurationsdatei, eine Datenbank-Spalte, typisiert als Text, und alle anderen Türen im Gebäude haben eine Regel gemeinsam: nur druckbare Zeichen. Base64 ist der Türsteher, der das Binary hereinlässt. Er schreibt Ihre Bytes um in einen Strom aus Buchstaben, Ziffern, Plus, Schrägstrich und Gleichheitszeichen, so dass alles, was als Text reist, sie tragen kann. Und die gute Nachricht: Jedes Stück des Kodierers, das Sie je brauchen könnten, ist bereits in der .NET-Laufzeit. Keine Pakete, keine Komponenten, keine Zeremonie.
In einem Atemzug, denn die Startseite dieser Site geht tief ins Format selbst: Base64 nimmt drei Eingabe-Bytes und schreibt sie als vier Zeichen aus einem Alphabet von 64 Symbolen, und fügt ein oder zwei =-Zeichen am Ende hinzu, wenn die Byte-Anzahl nicht gleichmäßig aufgeht. Dieser Vier-gegen-Drei-Tausch ist der Grund, warum kodierte Daten ungefähr ein Drittel größer sind als das Original, die berühmte Größen-Steuer, die Sie einmal pro Kodierung bezahlen. Alles andere in diesem Artikel dreht sich darum, dass die Kodierung, die Sie produzieren, genau das tut, was das nächste System erwartet: das richtige Alphabet, das richtige Padding, die richtigen Zeilenumbrüche und den richtigen Zeichensatz.
Der Kodierer-Werkzeugkasten: Alles ist eingebaut
Die Kodier-Seite der Laufzeit wuchs über dieselben vier Wellen wie die Dekodier-Seite, deshalb hat der Werkzeugkasten einen langen Schwanz von noch unterstützten Optionen. Hier ist die ganze Familie und der Job, für den jede gebaut wurde:
| API | Verfügbar seit | Wofür sie da ist |
|---|---|---|
System.Convert.ToBase64String |
.NET Framework 1.1 (2003) | Der Klassiker. Ein Array hinein, ein String heraus, mit Overloads für Array-Ausschnitte, Spans und optionale MIME-artige Zeilenumbrüche. |
System.Convert.ToBase64CharArray |
.NET Framework 1.1 (2003) | Schreibt die kodierten Zeichen in einen Zeichen-Puffer, den Sie bereits allokiert haben, und gibt zurück, wie viele Zeichen sie verwendet hat. |
System.Convert.TryToBase64Chars |
.NET Core 2.1 (2018) | Spanbasierte, allokationssparende Kodierung in einen Zeichen-Span, den Sie bereitstellen, mit einer booleschen Antwort statt einer Ausnahme. |
System.Buffers.Text.Base64 |
.NET Core 2.1 (2018) | Niedrigstufige, spanbasierte Kodierung: Schreiben Sie in Ihren eigenen UTF-8-Puffer, mit In-Place-Aufblähung und Puffer-Dimensionierung über GetMaxEncodedToUtf8Length. |
System.Buffers.Text.Base64Url |
.NET 9 (2024) | Das URL-sichere Alphabet (- und _ statt + und /) ohne Padding. Auf älteren Laufzeiten fährt es im Microsoft.Bcl.Memory-NuGet-Paket mit. |
ToBase64Transform + CryptoStream |
.NET Framework 1.1 (2003) | Streaming-Kodierung: Datei in Chunks lesen, kodierten Text heraus schreiben, Speicher bei riesigen Eingaben flach halten. |
Zur Versions-Landschaft: .NET 10 ist der aktuelle Langzeit-Support-Release (November 2025, unterstützt bis November 2028), .NET 8 und .NET 9 sind bis November 2026 unterstützt, und .NET 11 ist in der Vorschau mit einer frischen Ladung Base64-Komfortmethoden auf dem Weg. Alles in der Tabelle oben ist über alle Releases hinweg stabil. Die einzige Versionsgrenze ist Base64Url: fest eingebaut ab .NET 9, verfügbar auf .NET Framework 4.6.2 und neuer über das Microsoft.Bcl.Memory-Paket, und das ist das einzige Paket, das dieser Artikel überhaupt verlangt. Um ein Scratch-Projekt am Laufen zu bekommen, liefert das .NET-SDK Visual Basic von Haus aus:
dotnet new console -lang VB -o Packer
cd Packer
dotnet run
Ihre erste Kodierung: Bytes hinein, Text heraus
Neunzig Prozent des Kodier-Alltags in Visual Basic sind zwei Aufrufe, und die Reihenfolge zählt: Der Kodierer nimmt Bytes, nicht Text, deshalb wählen Sie, wenn Sie mit einem String starten, zuerst eine Kodierung, um ihn in Bytes zu verwandeln, und erst dann kommt der Base64-Schritt. Hier ist der ganze Tanz:
Imports System
Imports System.Text
Module Encoder
Sub Main()
Dim text As String = "Man"
Dim bytes() As Byte = Encoding.UTF8.GetBytes(text)
Dim packed As String = System.Convert.ToBase64String(bytes)
Console.WriteLine(packed)
' TWFu
End Sub
End Module
Dieser dreizeilige Mittelteil ist die ganze Kunst, und der String "TWFu" ist der perfekte Smoke-Test für jeden Kodierer, den Sie schreiben. Die Overloads geben Ihnen Kontrolle, wenn Sie sie brauchen. Die Subset-Formen kodieren einen Ausschnitt eines Arrays, ohne ihn zuerst herauszukopieren, was praktisch ist, wenn das echte Payload in einem größeren Puffer sitzt:
Imports System
Module SlicePacker
Sub Main()
Dim data() As Byte = {1, 2, 3, 4, 5, 6, 7, 8}
Dim packed As String = System.Convert.ToBase64String(data, 2, 4)
Console.WriteLine(packed)
' AwQFBg== (nur die Bytes 3 bis 6 wurden kodiert)
End Sub
End Module
Und die Array-zu-Char-Form, ToBase64CharArray, schreibt in einen Zeichen-Puffer, den Sie allokieren, und sagt Ihnen, wie viele Zeichen sie gefüllt hat, was das richtige Werkzeug ist, wenn das Ziel Teil einer größeren Textstruktur ist, die Sie von Hand bauen. Beachten Sie die Hausregel für Visual-Basic-Syntax: Ein Byte-Array wird als Byte() mit den leeren Klammern geschrieben. Lassen Sie sie weg, und Sie haben ein einzelnes Byte, und Option Strict On (in den Vorlagen standardmäßig aus - es lohnt sich, es in jedem Projekt einzuschalten) fängt die Verwechslung zur Kompilierzeit ab.
Die Ausgabe formen: Padding, Zeilenumbrüche und exakte Größen
Dieselben Bytes zweimal zu kodieren kann legitim zwei verschiedene Strings produzieren, und die Unterschiede liegen allesamt in der Ausgabe-Formung. Erstens, Padding: Wenn die Eingabe-Länge kein Vielfaches von drei ist, füllt der Kodierer die letzte Gruppe mit ein oder zwei =-Zeichen auf. Der RFC sagt, man solle sie einbeziehen, es sei denn, die Spezifikation, der Sie folgen, sagt etwas anderes, und ToBase64String bezieht sie standardmäßig ein. Zweitens, Zeilenumbrüche: Der zweite Parameter der Formatierungs-Overloads, Base64FormattingOptions.InsertLineBreaks, lässt den Kodierer 76-Zeichen-Zeilen mit CRLF-Trennung ausgeben, was genau die MIME-Regel ist. MIME selbst verwendet ein 76-Zeichen-Limit, einen engen Verwandten der alten 64-Zeichen-Zeilen von PEM, und beide Limits lassen sich auf Einschränkungen innerhalb von SMTP zurückführen. Wenn Ihr Konsument eine E-Mail-Pipeline ist, schalten Sie Zeilenumbrüche ein; wenn es eine URL, ein JSON-Feld oder eine Datenbank-Spalte ist, lassen Sie sie aus, denn ein unsichtbares CRLF in Ihren Daten wird einen Weg finden, Sie später zu überraschen:
Imports System
Module MimePacker
Sub Main()
Dim data(113) As Byte
For i As Integer = 0 To 113
data(i) = CByte(i)
Next
Dim wrapped As String = System.Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks)
Console.WriteLine(wrapped.Length)
' 154: zwei 76-Zeichen-Zeilen plus ein CRLF dazwischen
End Sub
End Module
Drittens, exakte Größen, denn Sie werden Puffer und Spaltenbreiten im Voraus allokieren wollen. Die Regel ist vier Zeichen für jedes drei Eingabe-Bytes, aufgerundet: 1000 Bytes werden zu 1336 Zeichen. Anstatt die Arithmetik von Hand zu machen, hat die Laufzeit einen Helper, der die maximale kodierte Länge für eine gegebene Eingabe-Größe zurückgibt, und genau das geben Sie an die Puffer-Allokation weiter:
Imports System.Buffers.Text
Module Sizing
Sub Main()
Dim dataLength As Integer = 1000
Dim textNeeded As Integer = Base64.GetMaxEncodedToUtf8Length(dataLength)
Console.WriteLine(textNeeded)
' 1336
End Sub
End Module
Dieses gleiche Vier-zu-Drei-Verhältnis ist die Größen-Steuer in ihrer reinsten Form: Jeder kodierte Wert ist ungefähr 33 Prozent größer als die Bytes, die er trägt, deshalb planen Sie Ihre Speicher- und Übertragungsgrößen mit diesem Spielraum im Kopf. Und ein Verhalten, das sich lohnt, es zu kennen, bevor es beißt: Wenn Sie einen String dekodieren und dann das Ergebnis neu kodieren, ist der neue String nicht garantiert gleich dem Original, weil Weißraum verschwindet und Padding normalisiert wird. Vergleichen Sie dekodierte Bytes, wenn Sie Werte vergleichen müssen, nicht den kodierten Text.
Den Zeichensatz wählen, bevor Sie kodieren
Weil der erste Schritt der Text-Kodierung "String zu Bytes" ist, entscheidet der Zeichensatz, den Sie wählen, was der Empfänger sieht, wenn er dekodiert. Visual-Basic-Strings sind UTF-16 innerhalb der Laufzeit, aber die Bytes, die Sie aussenden, sollten dem entsprechen, was die andere Seite erwartet zu lesen, und das Menü an Wahlmöglichkeiten ist kurz:
Encoding.UTF8: der richtige Standard für das Web, APIs und alles Moderne. Jedes Unicode-Zeichen, das die Sprache halten kann, übersteht damit die Rundreise.Encoding.Unicode: UTF-16 little-endian. Eine sinnvolle Wahl, wenn beide Enden der Pipe .NET-Programme sind, die ausdrücklich UTF-16 vereinbart haben, und nichts mehr.Encoding.ASCII: nur 7 Bit, und es ersetzt alles andere still und leise durch ein Fragezeichen. "Café" als ASCII zu kodieren ergibt die Bytes für "Caf?", was bei der Rück-Dekodierung genau das wird, Fragezeichen inklusive.Encoding.Default: Auf .NET Framework war das die ANSI-Codepage der Maschine, auf .NET (Core) ist es aber immer UTF-8, unabhängig vom Gebietsschema. Meiden Sie es trotzdem für Daten, die Sie austauschen - benennen Sie die Kodierung ausdrücklich, normalerweise UTF-8.
Imports System
Imports System.Text
Module CharsetPacker
Sub Main()
Dim text As String = "Café"
Dim utf8() As Byte = Encoding.UTF8.GetBytes(text)
Dim ascii() As Byte = Encoding.ASCII.GetBytes(text)
Console.WriteLine(System.Convert.ToBase64String(utf8))
' Q2Fmw6k=
Console.WriteLine(System.Convert.ToBase64String(ascii))
' Q2FmPw== (der Akzent wurde zu einem Fragezeichen)
End Sub
End Module
Zwei verschiedene Base64-Strings, ein Wort, und nur einer von ihnen übersteht die Reise. Die praktische Regel: Es sei denn, das Protokoll, dem Sie folgen, nennt ein anderes Schema, kodieren Sie Text als UTF-8 und sagen Sie es.
Base64Url: Das Alphabet, das URLs übersteht
Das Standard-Alphabet enthält + und /, und beide Zeichen haben eigene Aufgaben innerhalb von URLs, deshalb bricht Base64 auf Basis dieses Alphabets in dem Moment, in dem es in einem Query-String oder Pfad-Segment landet. Die Lösung, standardisiert in Abschnitt 5 von RFC 4648, tauscht die zwei Übeltäter gegen - und _ aus, die URL-sicher sind, und streicht typischerweise das Padding am Ende, weil die Datenlänge dem Dekodierer bereits sagt, wo die Daten enden. Diese Variante, bekannt als base64url, ist das Alphabet von JWTs, API-Tokens und einer wachsenden Zahl von APIs. .NET 9 hat eine eigene Klasse dafür hinzugefügt, und sie ist mit einer Meinung gebaut, die sich zu kennen lohnt: Sie lässt Padding aus Design-Gründen aus:
Imports System.Buffers.Text
Module UrlSafePacker
Sub Main()
Dim data() As Byte = {219, 255, 0, 63, 16}
Dim packed As String = Base64Url.EncodeToString(data)
Console.WriteLine(packed)
' 2_8APxA (Unterstrich, kein Padding am Ende)
End Sub
End Module
Das Beispiel oben ist ein gutes: Die gewählten Bytes bringen eines der Sonderzeichen zum Vorschein - den Unterstrich, wo das Standard-Alphabet einen Schrägstrich hat - so können Sie den Tausch geschehen sehen. Wenn Sie an einer älteren Laufzeit sind, ist dasselbe Alphabet zwei Zeichen-Ersetzungen plus ein Trimmen, und Sie bekommen ein Drop-in-kompatibles Ergebnis:
Imports System
Module CompatPacker
Function ToUrlSafe(ByVal packed As String) As String
Return packed.Replace("+"c, "-"c).Replace("/"c, "_"c).TrimEnd("="c)
End Function
End Module
Auf .NET Framework 4.6.2 oder neuer gibt Ihnen das Microsoft.Bcl.Memory-Paket stattdessen die echte Base64Url-Klasse. Auf jeden Fall beachten Sie die Padding-Grenze: Die Base64Url-Ausgabe von .NET hat kein Padding, während einige Bibliotheken in anderen Ökosystemen es hinzufügen (und ein paar strenge Dekodierer darauf bestehen). JWT verlangt zum Beispiel die ungepaddete Form, deshalb ist der .NET-Standard dort genau richtig. Wenn Sie eine Ökosystem-Grenze überschreiten, prüfen Sie die Erwartung der anderen Seite, bevor Sie den String versenden.
Dateien packen
Dateien sind der ursprüngliche Anwendungsfall: eine Binärdatei in eine Textdatei verwandeln, die E-Mail, FTP und Konfigurations-Systeme alle gerne tragen. In Visual Basic ist die ganze Aufgabe drei Aufrufe, einer liest und einer schreibt:
Imports System.IO
Module FilePacker
Sub Main()
Dim bytes() As Byte = File.ReadAllBytes("photo.png")
Dim packed As String = System.Convert.ToBase64String(bytes)
File.WriteAllText("photo.b64", packed)
End Sub
End Module
Halten Sie das Größen-Verhältnis in der Tasche: Ein 10-Megabyte-Foto wird zu einer Textdatei von etwa 13,4 Megabytes. Die Operation ist auf moderner Hardware schnell (mehr dazu unten), deshalb sind die Kosten fast immer Speicher und Bandbreite statt CPU, was die übliche Rechnung für eine 33-Prozent-Steuer ist. Wenn die Datei nur neben dem Text leben wird, der sie referenziert, ist dieses Muster vollkommen in Ordnung; wenn die Datei groß und langlebig ist, fragen Sie sich, ob der Kanal die Textform wirklich braucht.
Bilder: Data-URIs von Hand bauen
Das Data-URI-Schema (RFC 2397) bettet Dateiinhalte direkt in eine URL ein: data:, der Medientyp, der wörtliche Markierer ;base64, ein Komma und die kodierten Bytes. Browser nutzen sie, um kleine Bilder und Schriften inline einzubetten. WPF kann einen Data-URI nicht direkt konsumieren - BitmapImage hat keinen Handler für das data:-Schema - deshalb ist der idiomatische Zug, das Präfix abzuschneiden und die Bytes einem MemoryStream zu übergeben. Das Bauen des URI in Visual Basic ist eine String-Konkatenation, und der Konsum ein kleiner Init-Block:
Imports System.IO
Imports System.Windows.Media.Imaging
Module DataUriPacker
Sub Main()
Dim bytes() As Byte = File.ReadAllBytes("logo.png")
Dim dataUri As String = "data:image/png;base64," & System.Convert.ToBase64String(bytes)
Dim image As New BitmapImage()
image.BeginInit()
image.StreamSource = New MemoryStream(System.Convert.FromBase64String(dataUri.Substring(dataUri.IndexOf(","c) + 1)))
image.EndInit()
' Das Bild kann jetzt einer Image-Steuerung zugewiesen werden
End Sub
End Module
Der RFC selbst warnt, dass Data-URIs nur für kurze Werte nützlich sind, und HTML-Dokumente verhängen ihre eigenen Attribut-Längen-Grenzen, deshalb ist der sinnvolle Bereich Icons, Avatare, Thumbnails und winzige Hintergrund-Muster. Der Medientyp muss zu den Bytes passen, die Sie tatsächlich kodiert haben, denn nichts Nachgelagertes wird ihn aus dem Inhalt neu ableiten.
HTTP: Auth-Header und JSON-Payloads
Auf dem Draht sind die zwei Orte, an denen Sie von Hand kodieren, der HTTP-Basic-Auth-Header und JSON-Felder, die Binärdaten oder vorab kodierte Daten tragen. Basic Auth ist das sichtbarste: Der Header ist das Wort Basic, ein Leerzeichen und das Base64 von username:password, verbunden mit einem Doppelpunkt. Das Bauen davon ist ein Kodier-Aufruf:
Imports System
Imports System.Text
Module AuthPacker
Function MakeBasicHeader(ByVal user As String, ByVal password As String) As String
Dim raw() As Byte = Encoding.UTF8.GetBytes(user & ":" & password)
Return "Basic " & System.Convert.ToBase64String(raw)
End Function
End Module
Der JSON-Fall ist ebenso Routine. Wenn eine API ein Bild oder ein Zertifikat in einem Request-Body will, kodieren Sie die Bytes und stecken den String in das Payload, und System.Text.Json (in der Box seit .NET Core 3.0) kümmert sich um die Serialisierung drumherum:
Imports System.Text.Json
Module ApiPacker
Function WidgetPayload(ByVal name As String, ByVal imageBytes() As Byte) As String
Dim payload = New With {
.name = name,
.image = System.Convert.ToBase64String(imageBytes)
}
Return JsonSerializer.Serialize(payload)
End Function
End Module
Zwei Hausregeln: Senden Sie Zugangsdaten nur über HTTPS, denn über plain HTTP ist das Base64 ein Kostüm, kein Schloss, und loggen Sie niemals den rohen Auth-Header oder die Zugangsdaten, zu denen er dekodiert.
E-Mail-Anhänge und MIME-Umbruch
Die E-Mail ist der Ort, an dem Base64 seinen Lebensunterhalt verdient hat. SMTP wurde für 7-Bit-ASCII gebaut, deshalb muss ein binärer Anhang zu Text werden, bevor er fliegen kann, und der MIME-Standard (RFC 2045) traf die Wahl: Base64, umgebrochen bei 76 Zeichen pro Zeile, deklariert mit einem Content-Transfer-Encoding: base64-Header. Wenn Sie mit den System.Net.Mail-Klassen arbeiten, ist die ganze Zeremonie zwei Zeilen Setup, denn die Mail-Bibliothek macht den Umbruch für Sie zum Sendezeitpunkt:
Imports System.IO
Imports System.Net.Mail
Imports System.Net.Mime
Module MailPacker
Sub Main()
Using message As New MailMessage("me@example.com", "you@example.com")
message.Subject = "Quarterly report"
message.Body = "Please find the report attached."
Using stream As New FileStream("report.bin", FileMode.Open, FileAccess.Read)
Dim attachment As New Attachment(stream, "report.bin")
attachment.TransferEncoding = TransferEncoding.Base64
message.Attachments.Add(attachment)
End Using
End Using
End Sub
End Module
Die umgebrochene Form müssen Sie nur selbst produzieren, mit Base64FormattingOptions.InsertLineBreaks, wenn Sie rohen MIME-Text von Hand schreiben: eine Mailer-Test-Fixture, ein Legacy-Gateway oder ein Werkzeug, das .eml-Dateien ausspuckt. Die 76-Zeichen-Regel ist kein Stil-Wunsch; einige empfangende Systeme kürzen längere Zeilen, deshalb hat das Limit im Standard seit Jahrzehnten überlebt.
Kodierte Werte speichern: Datenbanken, Konfigurationsdateien und Umgebungsvariablen
Nur-Text-Speicher fragt ständig nach Base64: eine Datenbank-Spalte, typisiert als Text, ein XML-Konfigurationswert, eine Umgebungsvariable. Sie kodieren die Bytes, speichern den String und dekodieren ihn auf dem Weg hinaus. Die Kodier-Seite ist immer derselbe Einzeiler, aber die Speicher-Seite hat Grenzen, die die Größen-Steuer konkret machen. Eine gewöhnliche VARCHAR-Spalte in SQL Server hört bei 8.000 Zeichen auf (eine NVARCHAR-Spalte hört bei der Hälfte davon auf, 4.000 Zeichen, da jedes Unicode-Zeichen zwei Bytes kostet) - 8.000 Zeichen ist Platz für etwa 6.000 Bytes Binär, bevor der 33-Prozent-Overhead Sie über die Grenze drückt, darüber hinaus greifen Sie zu den MAX-Typen oder, ehrlicher gesagt, zu einer echten Binärspalte. Auf Windows ist eine einzelne benutzerdefinierte Umgebungsvariable auf 32.767 Zeichen gedeckelt (und auf XP-Ära-Systemen war der gesamte Umgebungsblock ebenfalls auf diese Größe gedeckelt), deshalb hat "den ganzen Lizenz-Blob in eine Umgebungsvariable legen" eine harte Obergrenze:
Imports System
Module EnvPacker
Sub Main()
Dim blob() As Byte = {1, 2, 3, 4, 5}
Dim packed As String = System.Convert.ToBase64String(blob)
Environment.SetEnvironmentVariable("APP_BLOB", packed)
Console.WriteLine(packed)
' AQIDBAU=
End Sub
End Module
Konfigurationsdateien folgen derselben Form, mit dem Wert, der in XML- oder JSON-Text lebt, und dem Dekodieren, das in Ihrem Start-Code passiert. Ein Legacy-Hinweis für die Enterprise-Ecke: WCF und XML-Data-Contracts serialisieren ein Byte-Array als den base64Binary-XML-Schema-Typ, deshalb speichert ein großer Bestand älterer .NET-Dienste Binär genau auf diese Weise, und der Wert, den Sie in diesem XML finden, ist plain ToBase64String-Ausgabe.
JWTs: Die kompakte Form bauen
Ein JSON Web Token in kompakter Form ist drei durch Punkte getrennte Teile aus base64url: der Header, das Payload und eine Signatur. Die ersten beiden sind normales JSON, und das dritte ist ein kryptografischer Beweis, dass ein Halter des richtigen Schlüssels dieses Token gebaut hat. Die unsignierte Form von Hand zu bauen ist zwei Kodierungen und ein String-Verbinden, aber ein echtes JWT braucht den Signatur-Schritt, und ein kleines HMAC-SHA256-Beispiel macht das ganze Ding konkret:
Imports System
Imports System.Buffers.Text
Imports System.Security.Cryptography
Imports System.Text
Module JwtPacker
Function BuildHs256Jwt(ByVal headerJson As String, ByVal payloadJson As String, ByVal secret() As Byte) As String
Dim header As String = Base64Url.EncodeToString(Encoding.UTF8.GetBytes(headerJson))
Dim body As String = Base64Url.EncodeToString(Encoding.UTF8.GetBytes(payloadJson))
Dim signingInput As String = header & "." & body
Using hmac As New HMACSHA256(secret)
Dim signature() As Byte = hmac.ComputeHash(Encoding.UTF8.GetBytes(signingInput))
Return signingInput & "." & Base64Url.EncodeToString(signature)
End Using
End Function
End Module
Führen Sie es mit dem Header {"alg":"HS256","typ":"JWT"} und einem Payload Ihrer Wahl aus, und das Ergebnis ist ein echtes kompaktes JWT: kein Padding irgendwo, URL-sichere Zeichen in allen drei Teilen. Beachten Sie, dass die Signatur auch base64url ist, weil das gesamte Token eine URL oder einen HTTP-Header überleben muss. Für Produktionssysteme baut, signiert und verifiziert das System.IdentityModel.Tokens.Jwt-Paket (die IdentityModel-Suite vom Microsoft-Entra-Team) diese Tokens für Sie, und das ist die Ebene, an der Schlüsselverwaltung, Algorithmus-Pinning und Ablauf-Checks zu Hause sind. Das Selbst-Bauen der Kodierung ist in Ordnung für das Verständnis und für kleine Werkzeuge; für alles, was Zugriff schützt, lassen Sie die Bibliothek das Gewicht tragen.
Fallen: Wo VB-Kodierer ausrutschen
Die Fallen hier sind ein Mix aus Sprach-Gewohnheiten und Ausgabe-Formungs-Überraschungen, und die meisten kosten eine Debugging-Session statt eines Crashes:
- Byte gegenüber Byte(). Der Kodierer will ein Array. In Visual Basic ist ein einzelnes Byte
Byteund ein Array istByte(), und der Unterschied ist ein Paar Klammern. UnterOption Strict Onist ein falscher Tipp ein Kompilierfehler; wenn es aus ist, bekommen Sie stattdessen vielleicht eine Laufzeit-Überraschung. Halten Sie die Strenge an und die Klammern sichtbar. - Die Encoding.Default-Falle, in umgekehrter Richtung. Die Geschichte der Gebietsschema-Ausweichung ist die von .NET Framework: Auf modernem .NET ist
Defaultimmer UTF-8, deshalb kodiert derselbe String auf jeder Maschine auf dieselbe Weise. Für alles, was Maschinen kreuzt, benennen Sie die Kodierung ausdrücklich, normalerweise UTF-8 - der Rat gilt in jedem Fall. - CRLF hat einen Weg hinein.
InsertLineBreaksist wunderbar für MIME und furchtbar für URLs, JSON und Datenbank-Textspalten, wo es einen Wagenrücklauf und einen Zeilenvorschub einfügt, den niemand verlangt hat. Verwenden Sie es nur, wenn der Konsument umgebrochene Zeilen erwartet, und wenn Sie unsicher sind, verwenden Sie den StandardNone. - Padding-Unstimmigkeiten an der Grenze. Die
Base64Urlvon .NET gibt kein Padding aus, während einige Bibliotheken in anderen Ökosystemen es hinzufügen (und ein paar strenge Dekodierer es verlangen). Wenn Ihr kodierter Wert ein Ökosystem kreuzt, bestätigen Sie die Erwartung der anderen Seite, bevor Sie den String versenden; JWT will die ungepaddete Form, was der .NET-Standard ist. - Rundreisen sind keine Identität. Dekodieren Sie einen umgebrochenen, gepaddeten String und kodieren Sie ihn neu, und Sie bekommen eine saubere einzelne Zeile mit frischem Padding, nicht den Originaltext. Wenn Ihre Logik kodierte Werte auf Gleichheit vergleicht, vergleichen Sie stattdessen die dekodierten Bytes.
- Die Größen-Obergrenze ist real. Die Ausgabe-Längen-Formel, vier Zeichen pro drei Bytes aufgerundet, überläuft eine 32-Bit-Zählung bei rund 1,5 Gigabyte Eingabe, und der Kodierer antwortet mit einer
OutOfMemoryExceptionstatt einem teilweisen String. Für Eingaben irgendwo in der Nähe dieser Größenordnung streamen Sie stattdessen (unten). - Die Span-Mauer. Die spanbasierten Kodierer sind aus VB an der Aufrufstelle aufrufbar: Geben Sie Ihre
Byte()- oderChar()-Arrays direkt hinein, und der Compiler wandelt sie um. Aber Sie können keine Variable, kein Feld und keinen Parameter vom TypSpanoderReadOnlySpandeklarieren; der Compiler verweigert es mit "Types with embedded references are not supported in this version of your compiler". Das VB-Idiom ist, die Span-APIs mit normalen Arrays aufzurufen und niemals einen Span zu speichern. - BitConverter ist nicht Base64.
BitConverter.ToString(bytes)rendert Hex mit Gedankenstrichen zwischen den Paaren, es ist also eine verlockende falsche Antwort, die4D-61-6Eproduziert, wo das andere SystemTWFuerwartet. Für Base64 ist die KlasseSystem.Convert, jedes Mal.
Geschwindigkeit und Größe: Leistungs-Notizen
Der Ruf von Base64 als "langsamer Text-Codec" überlebt den Kontakt mit der modernen Laufzeit nicht. Der Kodierer innerhalb von .NET führt hardwarevektorierten Code aus, wenn die Maschine es unterstützt, mit dedizierten Schnellpfaden für die AVX-512-, AVX2- und SSE-Befehlssätze, und der AVX-512-Pfad verarbeitet 48 Bytes pro Schritt. Für gewöhnliche Payloads ist der klassische ToBase64String-Aufruf schnell genug, dass der Algorithmus selten der Flaschenhals ist; die Kosten, die Sie spüren, sind die 33-Prozent-Größen-Steuer und, für heiße Pfade, die Zwischen-Allokationen. Wenn Sie Millionen kleiner Werte kodieren, sind die spanbasierten APIs die Verfeinerung: TryToBase64Chars schreibt in einen Zeichen-Span, den Sie kontrollieren, und meldet Erfolg mit einem Booleschen Wert, und System.Buffers.Text.Base64 geht noch weiter, indem es direkt in UTF-8-Puffer kodiert, die Sie allokieren, und Daten sogar in place aufbläst:
Imports System
Imports System.Buffers
Imports System.Buffers.Text
Imports System.Text
Module BufferPacker
Sub Main()
Dim data() As Byte = {1, 2, 3, 4, 5}
Dim textLength As Integer = Base64.GetMaxEncodedToUtf8Length(data.Length)
Dim buffer(textLength) As Byte
Dim written As Integer
Dim consumed As Integer
Dim status As OperationStatus = Base64.EncodeToUtf8(data, buffer, consumed, written)
Dim packed As String = Encoding.ASCII.GetString(buffer, 0, written)
Console.WriteLine(packed)
' AQIDBAU=
End Sub
End Module
Das Muster, das man beachten sollte, ist, dass Sie den Puffer mit dem Helper dimensionieren, in ihn kodieren und nur das verwendete Präfix in einen String umwandeln, was die Zwischenfläche so klein wie möglich hält. Und für Dateien, die groß genug sind, um Strings unangenehm zu machen, hält das Streaming-Paar den Speicher flach: Die ToBase64Transform-Transformation, eingewickelt in einen CryptoStream, liest Ihre Eingabe in Chunks und schreibt kodierten Text raus, so muss eine zwei-Gigabyte-Datei niemals auf einmal zu einem 2,7-Gigabyte-String werden:
Imports System.IO
Imports System.Security.Cryptography
Module StreamPacker
Sub EncodeFile(ByVal inputPath As String, ByVal packedPath As String)
Using inputStream As New FileStream(inputPath, FileMode.Open, FileAccess.Read)
Using packedStream As New CryptoStream(New FileStream(packedPath, FileMode.Create), New ToBase64Transform(), CryptoStreamMode.Write)
Dim buffer(65535) As Byte
While True
Dim read As Integer = inputStream.Read(buffer, 0, buffer.Length)
If read = 0 Then Exit While
packedStream.Write(buffer, 0, read)
End While
End Using
End Using
End Sub
End Module
Ein Hinweis nach vorn: Die Preview-Bibliotheken von .NET 11 fügen den bestehenden Base64-Typen neue Komfort- und Span-Overloads hinzu, deshalb wächst der Werkzeugkasten weiter, wenn Ihr Projekt Previews folgen kann; wenn nicht, ist alles Obige auf jedem unterstützten Release stabil.
Eine kurze Geschichte: Von MSXML zu Spans
Lange vor .NET entliehen Visual-Basic-Programme, die Base64 brauchten, es von der COM-Welt. Der klassische VB6- und VBA-Trick (die Makro-Sprache, die heute noch in Excel und Office läuft) benutzte stattdessen ein XML-DOM-Element: Der MSXML-Parser lässt einen Knoten seinen DataType als bin.base64 deklarieren, so dass das Schreiben Ihrer Bytes in die nodeTypedValue des Knotens und das Zurücklesen seiner text-Eigenschaft Ihnen den kodierten String in die Hand gibt, während das DOM die eigentliche Base64-Mathematik erledigt (das ADO-Stream-Objekt besitzt eine eigene Charset-Eigenschaft, die nur echte Zeichensatz-Namen wie "utf-8" oder "iso-8859-1" versteht, nicht "base64", deshalb spielt sie keine Rolle in der Umwandlung selbst). Es war clever, es war überall, und es ist der Grund, warum "base64 VBA" Suchmaschinen noch Jahrzehnte später aufleuchten lässt. Die Ära endete 2002, als die erste .NET-Version der Sprache, Visual Basic 7.0, der neuen Common Language Runtime beitrat, und das .NET Framework System.Convert mit ToBase64String von Haus aus brachte. Ab .NET Framework 1.1 im Jahr 2003 konnte jedes VB-Programm Base64 mit einem Aufruf kodieren, ohne Komponenten zu registrieren.
Die modernen Kapitel sind kurz. 2018 fügte .NET Core 2.1 die allokationssparende TryToBase64Chars-Methode und die niedrigstufige, spanbasierte System.Buffers.Text.Base64-Klasse hinzu. 2024 standardisierte .NET 9 das URL-sichere Alphabet als Base64Url und beendete ein Jahrzehnt handgemachter Replace-Aufrufe. Stand 2026 ist .NET 10 - im November 2025 veröffentlicht - der Langzeit-Support-Release, der all das mitträgt, und die Preview-Bibliotheken von .NET 11 fügen eine neue Generation von Komfortmethoden hinzu, deshalb ist der Kodierer von dem Einzeiler 2003 bis zur Span-Ära eine Geschichte derselben Klasse, die schneller und präziser wird, nie eine, bei der man von vorn anfängt.
Fun Facts, VB-Edition
InsertLineBreaksreproduziert die MIME-76-Zeichen-Regel exakt, CRLF inklusive, was bedeutet, dass die Zeilenumbrüche, die Ihr Kodierer 2026 schreibt, byte für byte dieselbe Form haben wie die, die ein E-Mail-Standard in den 1990ern definiert hat.- Der
IsNot-Operator, hinzugefügt mit Visual Basic 2005, war einmal eine Schlagzeile als Gegenstand einer Microsoft-Patentanmeldung. Sehr wenige Sprach-Operatoren können diese Auszeichnung beanspruchen. - Das erste Visual Basic kam 1991 auf den Markt, bevor das World Wide Web existierte. Bis das Data-URI-Schema 1998 erschien, hatte Base64 E-Mail-Anhänge schon fünf Jahre lang getragen, und VB war drei Jahre davor zu einer 32-Bit-Sprache herangewachsen, mit Visual Basic 4 im Jahr 1995.
- Auf Hardware mit AVX-512 verarbeitet der Laufzeit-Kodierer 48 Bytes pro Vektor-Schritt, was der Unterschied zwischen einem Tabellen-Lookup in einem Museum und einem Fließband in einer Fabrik ist.
- Der
My-Namespace, die berühmte Zucker-Schicht von Visual Basic aus 2005, brauchte nie einen Base64-Helper hinzuzufügen.System.Convertwar immer einen Namespace-Import entfernt, ein seltener Fall, in dem die VB-Laufzeit nichts zu einer Geschichte hinzufügte, die das Framework schon erzählte.
Die Kehrseite
Dieser Artikel hat die Kodier-Seite von Base64 in Visual Basic abgedeckt: den Werkzeugkasten, die Ausgabe-Formungs-Entscheidungen, das URL-sichere Alphabet und die Anwendungsfälle von Dateien bis JWTs. Die umgekehrte Richtung, einen eingehenden String zu nehmen und ihn zurück in die Bytes zu verwandeln, die er versteckt, hat ihren eigenen Satz von Verhaltensweisen, Verzeihungs-Regeln und Fallen, und sie wird in allen Details im Begleit-Artikel zur Dekodierung auf der Schwester-Site behandelt. Der Link dazu sitzt direkt unter dieser Zeile, und das Werkzeug auf der Startseite bleibt der schnellste Weg, ein kleines Payload von Hand zu kodieren.
Zuletzt aktualisiert: 2026-09-08
Verwandter Artikel: Base64-Dekodierung in Visual Basic: Ein vollständiger Leitfaden