Werk je met Base64-indeling? Dan is deze site perfect voor jou! Gebruik onze handige online tool om je gegevens te coderen of te decoderen.

Base64-decodering in Visual Basic: een complete gids

Stel je de scène voor: een string belandt in je Visual Basic-project. Het lijkt op een geschud kaartspel van letters en cijfers, met hier en daar een plus-teken, een slash of een equals-teken erdoorheen, en de persoon die het stuurt zweert dat het ooit een volstrekt gewone zin was, een JPEG of een config-blob. Die string is Base64, en deze pagina is je veldgids voor het terugbrengen naar wat het oorspronkelijk was. Het goede nieuws vooraf: Visual Basic heeft een eerste-klasses Base64-decoder al sinds de aller vroegste .NET Framework-dagen, die zit meegeleverd in de runtime, en je hoeft geen enkel pakket te installeren om hem te gebruiken.

Even een herhaling, want de startpagina van deze site legt het formaat in volle diepte uit: Base64 schrijft drie bytes weg als vier tekens uit een alfabet van 64 symbolen, en één of twee =-tekens aan de staart markeren waar de echte data ophield. Gecodeerde tekst is daardoor een beetje opgeblazen vergeleken met het origineel: vier tekens per drie invoerbytes, ruwweg een derde groter. Decoderen draait die ruil simpelweg om. Met de vorm van het probleem in het achterhoofd, laten we een paar enveloppen openen.

De decoderfamilie: één runtime, vier generaties

Alles wat je nodig hebt om te decoderen woont in de .NET-runtime. De laatste twintig jaar is die gegroeid in vier golven, en de oudere golven werken nog steeds exact zoals ze altijd deden, dus je zult ze allemaal in het wild tegenkomen:

API Beschikbaar sinds Waar het voor is
System.Convert.FromBase64String .NET Framework 1.1 (2003) Het klassieke. Eén string erin, een verse Byte()-array eruit. Gooit een uitzondering bij slechte input.
System.Convert.FromBase64CharArray .NET Framework 1.1 (2003) Dezelfde decodage, gelezen uit een stuk van een karakterarray die je al bezit.
System.Convert.TryFromBase64String, TryFromBase64Chars .NET Core 2.1 (2018) Een booleaanse waarde in plaats van uitzonderingen, schrijven naar een buffer die je aanlevert. De vriendelijke wachtpost voor onvertrouwde input.
System.Buffers.Text.Base64 .NET Core 2.1 (2018) Laaggevoegd, span-gebaseerd decoderen: statuscodes in plaats van uitzonderingen, decoderen op dezelfde plek, en IsValid-voorafchecks.
System.Buffers.Text.Base64Url .NET 9 (2024) Het URL-safe alfabet (- en _ in plaats van + en /), met optionele padding. Op oudere runtimes reist het mee in het Microsoft.Bcl.Memory NuGet-pakket.
FromBase64Transform + CryptoStream .NET Framework 1.1 (2003) Streamende decodage: bestand naar bestand, netwerk naar schijf, stuk voor stuk, zonder de hele payload in het geheugen te houden.

Een Visual Basic-toelichting voordat we verder gaan. In een VB-project lost de kale naam Convert op naar System.Convert, want de standaard projecttemplates importeren de System-namespace voor je, en niets in de Visual Basic-runtime overschaduwt die naam. Toch schrijft dit artikel grotendeels de volledige System.Convert-vorm: het kost niets, en het maakt de bedoeling onmiskenbaar voor iedereen die de code leest.

Over versies: .NET 10 is de huidige long-term-support-lijn (november 2025, ondersteund tot november 2028), en zowel .NET 8 als .NET 9 blijven ondersteund tot november 2026, terwijl .NET 11 in preview is en een reeks nieuwe Base64-gemaksmethoden toevoegt. De decoderings-API's zijn stabiel over al die versies heen. Het enige versiedrempel is Base64Url: die is ingebouwd vanaf .NET 9, en op .NET Framework 4.6.2 of nieuwer haal je hem binnen met het Microsoft.Bcl.Memory-pakket. Niets anders in dit artikel heeft een pakket nodig.

Als je vanaf nul opbouwt, levert de .NET SDK Visual Basic mee, dus dit is de hele ceremonie:

dotnet new console -lang VB -o EnvelopeOpener
cd EnvelopeOpener
dotnet run

Dat levert je een klein Program.vb op met Imports System bovenaan, en je kunt gaan decoderen.

De éénregelaar: FromBase64String

Negentig procent van het decoderingsleven in Visual Basic is een enkele aanroep. Geef hem een string, en hij geeft je precies de bytes terug die erin waren verpakt:

Imports System
Imports System.Text
Module EnvelopeOpener
    Sub Main()
        Dim packed As String = "TWFu"
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Dim text As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(text)
        ' Man
    End Sub
End Module

Drie dingen zijn het waard om te onthouden. Ten eerste is het resultaat bytes, geen tekst: de decoder is van begin tot eind byte-georiënteerd, en dat is precies wat je wilt, want de payload kan een zin zijn, een JPEG, een certificaat of een hash, en geen van die mag als speciaal worden behandeld. Van die bytes naar een leesbare string is een aparte, bewuste stap via een Encoding-object, en dat is de stap waar je charset-beslissing woont (daarover meer hieronder). Ten tweede allocereert FromBase64String een verse array, afgepast op exact de gedecodeerde lengte, zodat je nooit losse capaciteit rond je draagt. Ten derde decodeert "TWFu" naar het woord "Man", drie bytes, nul verrassingen, en daarmee is het de perfecte rooktest voor elke decodage-code die je schrijft.

Wat het vergeeft en wat het weigert

Hier heeft de .NET-decoder een persoonlijkheid, en een karaktervolle nog wel: hij is gul over precies één ding en genadeloos over alles andere. Het gulle ding is witruimte. De decoder slaat exact vier tekens over, waar ze ook voorkomen: de spatie (U+0020), de tab (U+0009), de line feed (U+000A) en de carriage return (U+000D). Dat beleid is een bewuste knik naar e-mail, waar Base64-payloads aankomen verpakt in korte regels, en het betekent dat een MIME-omwikkelde bijlage decodeert met nul voorverwerking. Een leuk feitje: deze tolerantie wordt gedeeld door de hele ingebouwde familie, inclusief de span-gebaseerde System.Buffers.Text.Base64 en de URL-safe Base64Url-klassen, dus je krijgt hetzelfde nadenige gedrag, welke API je ook pakt. Alles buiten het alfabet van 64 symbolen, alles dat de lengteregels breekt, of alles met padding op de verkeerde plek kost een uitzondering. Zie dezelfde decoder in actie op een paar verschillende inputs:

Input Resultaat
"TWFu" Decodeert naar Man (3 bytes).
"TWF" + CRLF + "u" Decodeert naar Man. Regelafbrekingen onderweg zijn voor de decoder onzichtbaar.
"TWFu" + non-breaking space FormatException. Alleen de vier witruimtekens hierboven worden overgeslagen; een non-breaking space hoort daar niet bij.
"TWE" FormatException. Als witruimte wordt genegeerd, moet de lengte een veelvoud van 4 zijn.
"TWFu=" FormatException. Padding nadat de data is afgelopen, mag niet.
"====" FormatException. Meer dan twee paddingtekens is ongeldig.
"" of alleen witruimte Een lege byte-array. Een stille, geldige succes.
"TW=u" FormatException. Padding in het midden is ongeldig.

Dus het eerlijke contract is klein en makkelijk te onthouden: een Nothing-referentie gooit een ArgumentNullException, lege of alleen-witruimte-input decodeert naar een lege array, geldige input decodeert naar bytes, en alles andere dat ongeldig is gooit één heel specifieke uitzondering: FormatException.

Van bytes naar tekst: de charset kiezen

Op het moment dat je beslist dat de gedecodeerde bytes eigenlijk tekst zijn, moet je een charset noemen, want bytes zijn geen tekst totdat je zegt hoe ze gelezen moeten worden. Visual Basic-strings zijn intern UTF-16, maar de bytes die uit de decoder komen zijn gemaakt door iemand anders, waarschijnlijk volgens een ander schema, dus je moet hun keuze volgen. Het praktische menu:

  • Encoding.UTF8: de veilige standaard voor alles dat over het web of door een API reisde. Twijfel je, begin hier.
  • Encoding.Unicode: UTF-16 little-endian, de inheemse smaak van .NET. Redelijk wanneer beide kanten van de uitwisseling .NET-programma's zijn die bewust UTF-16 kozen.
  • Encoding.ASCII: alleen 7-bit. Niet-ASCII-bytes worden vervangen door een vraagteken, dus dit is een keuze met verlies die stilletje accenten kapotmaakt.
  • Encoding.Default: op .NET Framework was dit de ANSI-codepagina van de machine, maar op .NET (Core) is het altijd UTF-8, ongeacht de locale. Vermijd het ook nog steeds voor data die je uitwisselt - noem de encoding expliciet, meestal Encoding.UTF8.
Imports System
Imports System.Text
Module CharsetDemo
    Sub Main()
        ' Het woord "Café" opgeslagen als UTF-8-bytes
        Dim bytes() As Byte = System.Convert.FromBase64String("Q2Fmw6k=")
        Dim correct As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(correct)
        ' Café
    End Sub
End Module

Lees diezelfde vijf bytes in plaats daarvan met Encoding.Unicode en je krijgt een korte string onzin - een paar vreemde tekens uit het CJK-bereik plus een vervangingsteken - want de decoder koppelt de bytes twee per twee aan elkaar. Lees de UTF-8-bytes van "Café" met Encoding.ASCII en het accent wordt ??, een paar vraagtekens, want het accent is twee bytes in UTF-8. Geen van deze keuzes gooit een uitzondering; ze produceren gewoon stilletje de verkeerde tekst, en daarom is de charset een beslissing die je bewust maakt, geen standaard die je overerft.

Het URL-safe alfabet: Base64Url

Standaard Base64 gebruikt + en /, en beide tekens dragen hun eigen betekenis binnen URLs, dus een standaard alfabet kan een link breken zodra die in een query string belandt. De oplossing, gestandaardiseerd in sectie 5 van RFC 4648, is de URL- en bestandsnaam-veilige variant: hetzelfde schema van 64 tekens met - op de plek van + en _ op de plek van /, en de padding aan de staart die doorgaans wordt weggehaald omdat de lengte die al impliceert. Je zult dit alfabet tegenkomen in JWTs, API-tokens en overal waar Base64 meereist in een URL. .NET 9 voegde een toegewijde klasse toe voor dit alfabet, System.Buffers.Text.Base64Url, en het is een feest om te gebruiken:

Imports System.Buffers.Text
Imports System.Text
Module UrlSafeOpener
    Sub Main()
        ' URL-safe input, geen padding aan het einde
        Dim packed As String = "SGVsbG8gd29ybGQ"
        Dim bytes() As Byte = Base64Url.DecodeFromChars(packed)
        Dim text As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(text)
        ' Hello world
    End Sub
End Module

Twee gedragingen zijn het weten waard. De Base64Url-encoder produceert met opzet zonder padding, maar zijn decoder accepteert zowel input met padding als zonder, dus hij is vriendelijk voor data uit andere ecosystemen. En Base64Url.IsValid laat je een kandidaat-string vooraf checken vóórdat je decodeert, wat handig is wanneer de data van buitenaf komt. Als je vastzit op een oudere runtime zonder de klasse, is de omzetting twee karakterswaps en een padding-aanvulling, exact het omgekeerde van wat de encoder deed:

Imports System
Module CompatOpener
    Function FromUrlSafe(ByVal packed As String) As Byte()
        Dim standard As String = packed.Replace("-"c, "+"c).Replace("_"c, "/"c)
        Select Case standard.Length Mod 4
            Case 2
                standard &= "=="
            Case 3
                standard &= "="
        End Select
        Return System.Convert.FromBase64String(standard)
    End Function
End Module

Op .NET Framework 4.6.2 of nieuwer kun je in plaats daarvan het Microsoft.Bcl.Memory NuGet-pakket installeren en de echte Base64Url-klasse gebruiken. Beide wegen volgen dezelfde eenvoudige regel: herken het alfabet aan de context (URL, JWT, API-token), en kies daarna de passende decoder.

Bestanden openen

Eén van de oudste toepassingen van Base64 is binaire data smokkelen via tekstbestanden: een .b64- of .txt-bestand met gecodeerde bytes. In Visual Basic is de rondrit twee bestandaanroepen en één decodage. Lees de tekst, decodeer die, schrijf de bytes weg:

Imports System.IO
Module FileOpener
    Sub Main()
        Dim packed As String = File.ReadAllText("payload.b64")
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        File.WriteAllBytes("payload.bin", bytes)
    End Sub
End Module

De witruimte-tolerantie maakt dit op een bevredigende manier robuust: het bestand maakt zich niets van de vraag of de payload als één lange regel werd geschreven, verpakt na 76 tekens, of verpakt na 64, want de decoder slaat de regelafbrekingen in beide gevallen over. Houd één maatfeit in je achterzak: het tekstbestand is ongeveer een derde groter dan de binaire data die het verbergt, dus een bestand van 10 megabyte komt aan als ruwweg 13,3 megabyte aan tekens. Niets dramatisch, maar het is het getal om te onthouden wanneer een "klein" tekstbestand groot aanvoelt.

Afbeeldingen en data-URIs

Het data-URI-schema (RFC 2397) laat een URL haar eigen inhoud meedragen: data: gevolgd door de media type, de letterlijke marker ;base64, een komma, en daarna de gecodeerde bytes. Je hebt het overal op het web gezien, in HTML en CSS, waar het kleine afbeeldingen en lettertypes direct in de markup embedt in plaats van naar een apart bestand te wijzen. In Visual Basic is het uitpakken ervan niets meer dan een stringsplit en een decodage. Het voorbeeld hieronder haalt een PNG uit een data-URI en bouwt daar een WPF-afbeelding van:

Imports System.IO
Imports System.Windows.Media.Imaging
Module DataUriOpener
    Function ImageFromDataUri(ByVal dataUri As String) As BitmapImage
        Dim comma As Integer = dataUri.IndexOf(","c)
        Dim header As String = dataUri.Substring(0, comma)
        If Not header.EndsWith(";base64") Then
            Throw New FormatException("Not a base64 data URI")
        End If
        Dim packed As String = dataUri.Substring(comma + 1)
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Dim image As New BitmapImage()
        image.BeginInit()
        image.CacheOption = BitmapCacheOption.OnLoad
        image.StreamSource = New MemoryStream(bytes)
        image.EndInit()
        Return image
    End Function
End Module

Let op de defensieve check op de header: een data-URI zonder de ;base64-marker bevat in plaats daarvan URL-geëscaleerde data, en dat als Base64 decoderen faalt of levert rommel op. De RFC zelf waarschuwt dat data-URIs alleen nuttig zijn voor korte waarden, en HTML heeft zijn eigen lengtelimieten voor attributes, dus behandel dit als het juiste gereedschap voor iconen, avatars en thumbnails, niet voor het verschepen van je hele fotobibliotheek in één attribute.

HTTP, API's en Basic auth

Base64 staat overal in web-API's, en de twee meest voorkomende verschijningsvormen zijn de HTTP Basic auth-header en JSON-velden die binaire of vooraf gecodeerde data meedragen. Basic auth is het eenvoudigste geval: de client stuurt Authorization: Basic gevolgd door de Base64 van username:password. Dat decoderen in Visual Basic is een prefix-check en één aanroep:

Imports System
Imports System.Text
Module BasicAuthOpener
    Function ReadCredentials(ByVal header As String) As String
        If Not header.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase) Then
            Throw New FormatException("Not a Basic auth header")
        End If
        Dim packed As String = header.Substring(6)
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Return Encoding.UTF8.GetString(bytes)
    End Function
End Module

De functie geeft username:password terug als één string, die je daarna splitst op de dubbele punt. Het andere alledaagse geval is een JSON-antwoord waarin een veld een vooraf gecodeerde blob is, zoals een afbeelding of een certificaat. Met HttpClient en System.Text.Json (System.Text.Json zit er sinds .NET Core 3.0 al meegeleverd, en HttpClient al veel langer) is het patroon eenvoudig:

Imports System.Net.Http
Imports System.Text.Json
Module ApiOpener
    Async Function ReadImageAsync() As Task(Of Byte())
        Using client As New HttpClient()
            Dim json As String = Await client.GetStringAsync("https://httpbin.org/get?attachment=TWFuIGlzIGhlcmU%3D&name=man.txt")
            Dim doc As JsonDocument = JsonDocument.Parse(json)
            Dim packed As String = doc.RootElement.GetProperty("args").GetProperty("attachment").GetString()
            Return System.Convert.FromBase64String(packed)
        End Using
    End Function
End Module

Twee huishoudelijke notities. Print een gedecodeerde credentiaal nooit naar een logboek of een UI, zomaar omdat je kunt, en steun nooit op Basic auth over plain HTTP, want dan heb je het wachtwoord alleen in een interessanter alfabet geschreven.

JWTs: de drie stukken lezen

Een JSON Web Token in zijn compacte vorm is drie puntgescheiden stukjes Base64Url: de header, de payload en de handtekening. De eerste twee zijn gewone JSON die je met je ogen kunt lezen (of met één decodage-aanroep), terwijl de derde een cryptografische handtekening is die met de juiste sleutel geverifieerd moet worden, niet gedecodeerd. Een voorbeeldtoken uit een veelgebruikte demo ziet er zo uit: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.W-5gI_FdnMBdpgG4twX96rptvh13gmXQ75kKLRXVaGs. De payload daarvan lezen in Visual Basic betekent: splitsen op de punten, het URL-safe alfabet terugzetten naar het standaard alfabet, en decoderen:

Imports System
Imports System.Text
Module JwtOpener
    Function ReadPayload(ByVal token As String) As String
        Dim parts() As String = token.Split("."c)
        If parts.Length <> 3 Then
            Throw New FormatException("Not a compact JWT")
        End If
        ' Het URL-safe alfabet terugzetten naar het standaard alfabet
        Dim packed As String = parts(1).Replace("-"c, "+"c).Replace("_"c, "/"c)
        Select Case packed.Length Mod 4
            Case 2
                packed &= "=="
            Case 3
                packed &= "="
        End Select
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Return Encoding.UTF8.GetString(bytes)
    End Function
End Module

Voer dat uit tegen het voorbeeldtoken en je krijgt de JSON {"sub":"1234567890","name":"John Doe"}. Lees de header op dezelfde manier en je krijgt {"alg":"HS256","typ":"JWT"}. De waarschuwing die hier telt: een JWT lezen is hem niet verifiëren. Iedereen kan een token fabriceren, dus voordat je een claim erin vertrouwt, valideer je de handtekening met de sleutel van de uitgever. Voor dat werk pakt het System.IdentityModel.Tokens.Jwt NuGet-pakket (de IdentityModel-suite van het Microsoft Entra-team) de Base64Url-details, de handtekeningcheck en het parsen van de claims voor je, en dat is precies de laag waar je niet zelf wil beginnen.

E-mailbijlagen, verpakt na 76 tekens

E-mail is waar Base64 zijn reputatie verdiende. SMTP was ontworpen voor 7-bit ASCII, dus een binaire bijlage moet eerst tekst worden vóórdat hij kan vliegen, en de MIME-standaard (RFC 2045) koos Base64 met een regellimiet van 76 tekens, een nauw familielid van de nog oudere regels van 64 tekens van PEM. Als je ooit een rauwe e-mail hebt ontvangen, heb je het resultaat gezien: een blok dichte Base64, opgebroken in nette korte regels, onder een Content-Transfer-Encoding: base64-header. Het mooie voor een decoder is dat je niets hoeft te ontpakken. De .NET-decoder slaat regelafbrekingen en spaties over, waar ze ook voorkomen, dus het verpakte blok decodeert zoals het is:

Imports System
Imports System.Text
Module MimeOpener
    Sub Main()
        ' Een zin van 59 bytes, MIME-verpakt na 76 tekens met CRLF
        Dim wrapped As String = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZywgYW5kIHRoZW4gc29t" & vbCr & vbLf & "ZS4="
        Dim bytes() As Byte = System.Convert.FromBase64String(wrapped)
        Console.WriteLine(Encoding.UTF8.GetString(bytes))
        ' The quick brown fox jumps over the lazy dog, and then some.
    End Sub
End Module

Als je werkt met de System.Net.Mail-klassen, is het decoderen nog onzichtbaarder: een Attachment die je aan een MailMessage toevoegt krijgt een ContentEncoding van TransferEncoding.Base64, en de mail-bibliotheek verpakt, stuurt en ontverpakt het hele ritueel voor je. Je hebt de handmatige decodage alleen nodig wanneer je rauwe MIME leest uit een stream, een testfixture, of een legacy mailboxbestand.

Databases, configuratie en omgevingsvariabelen

Opslag die alleen tekst accepteert blijft Base64 vragen: een databasekolom getypeerd als tekst, een XML-configuratiewaarde, een omgevingsvariabele. Ze willen allemaal gewone tekens, dus binair wordt gecodeerd vóórdat het wordt opgeslagen, en gedecodeerd wanneer het terugkomt. De decoderingskant is altijd dezelfde éénregelaar, en het interessante deel is de maatberekening. Een gewone NVARCHAR-kolom in SQL Server toppt af op 8.000 tekens, wat neerkomt op zo'n 6.000 bytes binair voordat de 33-procent-belasting je over de rand duwt; daarboven grijp je naar de MAX-varianten of, eerlijker gezegd, naar een echte binaire kolom. Op Windows is één door de gebruiker gedefinieerde omgevingsvariabele beperkt tot 32.767 tekens (en op XP-tijdperk-systemen was het hele omgevingsblok ook tot die maat beperkt), dus "de hele licentie-blob in een omgevingsvariabele stoppen" heeft een hard plafond. Hier is een decodagepatroon dat de moeite waard is om in een hoekje van je hoofd te bewaren: een opgeslagen vingerafdruk vergelijken met een bestand, met een vergelijking in constante tijd zodat een onevenkomst geen timing-informatie lekt:

Imports System.Security.Cryptography
Module FingerprintCheck
    Function FingerprintsMatch(ByVal expectedPacked As String, ByVal fileBytes() As Byte) As Boolean
        Dim expected() As Byte = System.Convert.FromBase64String(expectedPacked)
        Dim actual() As Byte = SHA256.HashData(fileBytes)
        Return CryptographicOperations.FixedTimeEquals(expected, actual)
    End Function
End Module

Dezelfde vorm werkt voor elke opgeslagen hash: decodeer de opgeslagen waarde, bereken de verse hash, en vergelijk in vaste tijd. Config-bestanden volgen het identieke patroon, of de waarde nu van een XML-app.config-entry komt, van een JSON-instellingenbestand, of van een registry-string.

Grote data: een stream decoderen zonder hem te laden

Elk voorbeeld tot nu toe heeft de hele payload in het geheugen gelezen, wat prima is voor bijlagen en configuratiewaarden, maar verkeerd voor een bestand van twee gigabyte dat iemand in een tekstbestand heeft gecodeerd. Voor die schaal heeft .NET een stroomend duo dat al sinds .NET Framework 1.1 (2003) bestaat: de FromBase64Transform-cryptotransform, ingepakt in een CryptoStream. Je leest chunks van gecodeerde tekst, de transform decodeert ze op dat moment, en je schrijft de bytes weg, zodat het geheugen vlak blijft, hoe groot het bestand ook is:

Imports System.IO
Imports System.Security.Cryptography
Module StreamOpener
    Sub DecodeFile(ByVal packedPath As String, ByVal outputPath As String)
        Using packedStream As New FileStream(packedPath, FileMode.Open, FileAccess.Read)
            Using decodedStream As New CryptoStream(packedStream, New FromBase64Transform(), CryptoStreamMode.Read)
                Using outputStream As New FileStream(outputPath, FileMode.Create)
                    Dim buffer(65535) As Byte
                    While True
                        Dim read As Integer = decodedStream.Read(buffer, 0, buffer.Length)
                        If read = 0 Then Exit While
                        outputStream.Write(buffer, 0, read)
                    End While
                End Using
            End Using
        End Using
    End Sub
End Module

Omdat het gecodeerde bestand gewone ASCII-tekst is, is het lezen ervan als een bytestroom helemaal veilig, en de transform komt de regelomwikkeling zonder dat je iets hoeft te doen. Het uitvoerbestand komt eruit op zo'n driekwart van de grootte van de invoer, wat dezelfde 33-procent-belasting is die bij het binnenkomen betaald wordt en nu bij het uitgaan wordt ingevorderd.

Valkuilen met een VB-accent

De meeste vallen in deze sectie worden gedeeld met andere .NET-talen, maar een paar dragen een duidelijk VB-hoedje, dus hier zijn ze bij elkaar:

  • Byte versus Byte(). In Visual Basic is één byte Byte en een byte-array Byte(), waarbij de lege haakjes al het werk doen. Dim b As Byte schrijven terwijl je Byte() bedoelde is de klassieke eerste-dag-fout, en precies het soort ding dat Option Strict On op compileertijd vangt. Als je project het niet al aan heeft staan, zet het dan aan: de dotnet new console -lang VB-template laat de beslissing aan jou over, terwijl de Visual Studio-projecttemplates het wel instellen.
  • De span-muur. De moderne span-gebaseerde API's zijn vanuit VB aanroepbaar, maar alleen op de aanroepplaats: je kunt een Byte()- of Char()-array gewoon doorgeven aan een methode die een span verwacht, en de compiler zet hem om voor je. Wat je níét kunt doen, is een span noemen in je eigen code. Declareer een variabele, een veld of een parameter van het type Span of ReadOnlySpan, en de compiler antwoordt met "Types with embedded references are not supported in this version of your compiler". Dus het VB-idioom is: roep de span-API's aan met gewone arrays, en probeer nooit een span op te slaan in een variabele.
  • BitConverter is geen Base64. BitConverter.ToString(bytes) rendert bytes als hex, gescheiden door streepjes, wat het een verleidelijk fout antwoord maakt voor wie ooit "bytes naar string converteren" heeft gehoord. Hij geeft je zonder morren 4D-61-6E terwijl de API TWFu verwacht. Twijfel je, grijp dan naar System.Convert.
  • MidB is een spook. Klassiek Visual Basic had byte-georiënteerde stringfuncties, MidB, LeftB en RightB, gericht op tekensets met dubbele bytes. Elke .NET-string is nu Unicode, en de runtime-documentatie is helder: ze worden niet meer ondersteund. Als een legacy-fragment ze gebruikt, herschrijf het dan met byte-arrays en de API's uit dit artikel.
  • Encoding.Default volgt de machine. Het verhaal van locale-verschillen is het .NET Framework-verhaal: op moderne .NET is Default altijd UTF-8, dus dezelfde bytes decoderen overal op dezelfde manier. Voor data die je deelt, noem de encoding expliciet, meestal Encoding.UTF8 - het advies geldt in beide gevallen.
  • Rondritten zijn geen identiteit. Als je een string decodeert en daarna het resultaat encodeert, is de nieuwe string niet gegarandeerd identiek aan de oorspronkelijke: witruimte verdwijnt, en padding wordt genormaliseerd. Een payload met regelafbrekingen komt terug als één nette regel. Prima voor data, gevaarlijk als je logica de gecodeerde tekst vergelijkt in plaats van de gedecodeerde bytes.
  • Alleen-witruimte-input is een stille succes. Een string van alleen maar spaties en regelafbrekingen decodeert naar een lege byte-array zonder enige fout, wat betekent dat "de gebruiker plakte niets anders dan nieuwe regels" er exact hetzelfde uitziet als "de gebruiker plakte een lege payload". Als het onderscheid er toe doet, controleer dan de inputlengte vóórdat je decodeert.

Goede gewoonten voor het decoderen

Uit alles hierboven gedistilleerd, de gewoonten die decodage-code saai houden (in de beste zin van het woord):

  • Behandel Base64 als vervoer, niet als bescherming. Het is een encoding, geen encryptie: iedereen kan het origineel met één functieaanroep lezen, en RFC 4648 merkt zelfs op dat slordige alfabetafhandeling geheime kanalen kan openen. Encrypteer eerst, en encodeer daarna als je inhoud wilt verbergen.
  • Voor onvertrouwde input verleen je de voorkeur aan de Try-methodes of een IsValid-voorafcheck boven FormatException laten vliegen. Een booleaanse waarde is makkelijker te maken tot een vriendelijke foutmelding dan een uitzondering is te slikken.
  • Kies de charset bewust, en ga standaard naar UTF-8 tenzij je een gedocumenteerde reden hebt voor een ander schema.
  • Koppel het alfabet aan de bron: standaard Base64 voor MIME, e-mail en config; Base64Url voor JWTs en alles wat in een URL zit.
  • Stream alles groots door FromBase64Transform en CryptoStream, in plaats van het in een string te laden.
  • Vergelijk vingerafdrukken en hashes met CryptographicOperations.FixedTimeEquals, niet met =, zodat de timing niet lekt hoeveel van de waarde overeenkwam.
  • Houd Option Strict On aan, zodat de Byte/Byte()-familie aan struikelblokken een compileerfout wordt in plaats van een productiemysterie.

Hoe Visual Basic zijn decoder kreeg

Het verhaal begint in een tijdperk waarin Visual Basic helemaal geen Base64 had. In de wereld van Visual Basic 6 en VBA (de macrotaal die vandaag nog steeds draait in Excel en Office) leenden ontwikkelaars die Base64 nodig hadden hem uit bij de COM-componenten die al op de machine stonden. De beroemde truc gebruikte een XML DOM-element: de MSXML-parser laat een node zijn DataType declareren als bin.base64, zodat je door een Base64-string toe te wijzen aan de text-eigenschap van de node en diens nodeTypedValue terug te lezen de rauwe bytes in handen krijgt, met de DOM die het echte Base64-rekensorwerk doet (de eigen Charset-eigenschap van het ADO Stream-object begrijpt alleen echte charset-namen zoals "utf-8" of "iso-8859-1", niet "base64", en daarom grijpt de truc in plaats daarvan naar MSXML). Encoderen voerde hetzelfde idee in omgekeerde volgorde uit: bytes schrijven in nodeTypedValue en de gecodeerde string teruglezen uit text:

' De klassieke VB6 / VBA-decodagetruc, ter context
Dim node As Object
Set node = CreateObject("MSXML2.DOMDocument").createElement("b64")
node.DataType = "bin.base64"
node.text = packed            ' de Base64-string
Dim bytes() As Byte
bytes = node.nodeTypedValue

Het werkte, het was slim, en het is de reden waarom "base64 VBA" dertig jaar later nog steeds zoekmachines doet oplichten. Toen veranderde 2002 alles: Visual Basic 7.0 (de eerste .NET-versie van de taal, destijds nog Visual Basic .NET geheten) voegde zich bij de nieuwe Common Language Runtime, en het .NET Framework bracht System.Convert mee met FromBase64String en zijn vrienden, alles al meegeleverd. Vanaf .NET Framework 1.1 in 2003 had elk VB-programma een eerste-klasses decoder zonder componenten die geregistreerd moesten worden. De moderne golf arriveerde in 2018 met .NET Core 2.1, dat de uitzonderingsvrije Try-methodes en de snelle span-gebaseerde System.Buffers.Text.Base64-klasse toevoegde, en in 2024 met .NET 9, dat eindelijk het URL-safe alfabet standaardiseerde als Base64Url. Per 2026 is .NET 10 - uitgebracht in november 2025 - de long-term-support-lijn, en de preview .NET 11-bibliotheken voegen een nieuwe generatie Base64-gemaksmethoden toe, dus de decoder blijft beter worden, terwijl de oorspronkelijke éénregelaar van 2003 onveranderd doorgaat.

Leuke weetjes uit de VB-wereld

  • De officiële Visual Basic-compiler zelf is geschreven in Visual Basic. Als onderdeel van het open-source Roslyn-project compileert de taal zichzelf.
  • Het allereerste Visual Basic werd in 1991 uitgebracht, nog vóórdat het web-tijdperk van de grond was gekomen. Het grote moment van Base64 arriveerde met MIME in 1993, en VB zelf groeide twee jaar later een 32-bit-vermogen, toen Visual Basic 4 in 1995 voor het eerst 32-bit-programma's mogelijk maakte. VB 5 in 1997 ging helemaal: alleen maar 32-bit, geen 16-bit meer in de doos.
  • De byte-georiënteerde functies MidB, LeftB en RightB uit klassiek VB zijn officieel "niet meer ondersteund" in .NET, omdat elke VB-string sinds de eerste dag van de framework Unicode is. Een hele API-familie, gepensioneerd door een encodingskeus.
  • De Base64-machinerie van de runtime is geen sentimentaal tabelzoekje: de moderne implementatie draait hardware-gevectoriseerde codepaden (AVX-512-, AVX2- en SSE-varianten) wanneer de machine ze ondersteunt, dus er gebeurt geen "langzame tekst-codec" onder de motorkap.
  • De MSXML-bin.base64-truc uit het VB6-tijdperk draait vandaag nog steeds in productie-Excel-macro's, wat betekent dat een workaround uit eind jaren 1990 en een Convert-aanroep uit 2003 vredig samenleven in het codebase van dezelfde organisatie.

Vóórdat je vertrekt

Dit artikel heeft de decoderingskant van Base64 in Visual Basic behandeld, van de éénregelaar tot streaming, van JWTs tot de valkuilen die een VB-hoedje dragen. De andere helft van de munt, je bytes en tekst in de eerste plaats in Base64 omzetten, heeft zijn eigen set beslissingen over padding, regelafbrekingen en de groottebelasting, en die wordt in volle diepte behandeld in het bijbehorende encoderingsartikel op de zustersite. De link ernaartoe zit net onder deze regel, en het gereedschap op de startpagina blijft de snelste manier om een kleine payload met de hand te inspecteren.

Laatst bijgewerkt: 2026-10-06

Gerelateerd artikel: Base64-codering in Visual Basic: een complete gids