Vous avez à traiter le format Base64 ? Alors ce site est parfait pour vous ! Utilisez notre outil en ligne super pratique pour encoder ou décoder vos données.

Décodage Base64 en Visual Basic : un guide complet

Figurez-vous la scène : une chaîne atterrit dans votre projet Visual Basic. Elle ressemble à un jeu de cartes mélangé, lettres et chiffres entremêlés, avec de temps en temps un signe plus, une barre oblique ou un signe égal glissés au milieu, et celui qui vous l'a envoyée jure qu'elle fut un jour une tout à fait ordinaire phrase, un JPEG ou un blob de configuration. Cette chaîne est du Base64, et cette page est votre guide de terrain pour la ramener à ce qu'elle était. La bonne nouvelle, tout de suite : Visual Basic possède un décodeur Base64 de premier ordre depuis les tout débuts du .NET Framework, il est livré dans le runtime, et vous n'avez besoin d'installer le moindre paquet pour l'utiliser.

Un petit rappel, parce que la page d'accueil de ce site explique le format en profondeur : le Base64 écrit trois octets sous forme de quatre caractères tirés d'un alphabet de 64 symboles, et un ou deux caractères = à la queue marquent là où les vraies données se sont terminées. Le texte encodé est donc un peu gonflé par rapport à l'original : quatre caractères pour chaque groupe de trois octets en entrée, à peu près un tiers de plus. Le décodage suit simplement cet échange en sens inverse. Le contour du problème en tête, ouvrons quelques enveloppes.

La famille des décodeurs : un runtime, quatre ères

Tout ce qu'il faut pour décoder vit dans le runtime .NET. Ces vingt dernières années, il s'est agrandi en quatre vagues, et les vagues les plus anciennes fonctionnent encore exactement comme toujours, vous les croiserez donc toutes dans la nature :

API Disponible depuis À quoi ça sert
System.Convert.FromBase64String .NET Framework 1.1 (2003) Le classique. Une chaîne en entrée, un Byte() neuf en sortie. Lève une exception sur une entrée douteuse.
System.Convert.FromBase64CharArray .NET Framework 1.1 (2003) Le même décodage, en lisant dans une tranche d'un tableau de caractères que vous possédez déjà.
System.Convert.TryFromBase64String, TryFromBase64Chars .NET Core 2.1 (2018) Un booléen au lieu d'exceptions, écriture dans un tampon que vous fournissez. La garde amicale pour les entrées non fiables.
System.Buffers.Text.Base64 .NET Core 2.1 (2018) Décodage bas niveau, basé sur les spans : des codes d'état au lieu d'exceptions, un dégonflement in place, et des pré-vérifications IsValid.
System.Buffers.Text.Base64Url .NET 9 (2024) L'alphabet URL-safe (- et _ au lieu de + et /), avec padding optionnel. Sur les runtimes plus anciens, il voyage dans le paquet NuGet Microsoft.Bcl.Memory.
FromBase64Transform + CryptoStream .NET Framework 1.1 (2003) Le décodage en flux : de fichier à fichier, du réseau au disque, bloc par bloc, sans garder tout le payload en mémoire.

Une précision Visual Basic avant d'aller plus loin. Dans un projet VB, le nom nu Convert se résout en System.Convert, parce que les gabarits de projet standard importent l'espace de noms System pour vous, et que rien dans le runtime Visual Basic ne masque ce nom. Malgré tout, cet article écrit surtout la forme complète System.Convert : ça ne coûte rien, et cela rend l'intention incontestable pour quiconque lit le code.

Côté versions : .NET 10 est la version de support à long terme actuelle (novembre 2025, support jusqu'en novembre 2028), .NET 8 et .NET 9 restent tous deux pris en charge jusqu'en novembre 2026, tandis que .NET 11 est en aperçu et apporte un lot de nouvelles méthodes de confort Base64. Les API de décodage sont stables sur toutes ces versions. La seule porte de version est Base64Url : elle est intégrée à partir de .NET 9, et sur .NET Framework 4.6.2 ou plus récent, vous pouvez l'obtenir avec le paquet Microsoft.Bcl.Memory. Rien d'autre dans cet article ne demande de paquet.

Si vous partez de zéro, le SDK .NET inclut Visual Basic en standard, et la cérémonie complète tient en ceci :

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

Ça vous donne un petit Program.vb avec Imports System en haut, et vous êtes prêt à décoder.

Le one-liner : FromBase64String

Quatre-vingt-dix pour cent de la vie du décodage en Visual Basic tiennent dans un seul appel. Donnez-lui une chaîne, et il vous rend les octets exacts qui étaient emballés dedans :

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

Trois choses méritent d'être gravées en mémoire. D'abord, le résultat est des octets, pas du texte : le décodeur est orienté octets de bout en bout, c'est exactement ce qu'on veut, parce que le payload peut être une phrase, un JPEG, un certificat ou un hachage, et qu'aucun d'eux ne doit être traité à part. Transformer ces octets en chaîne lisible est une étape à part, délibérée, qui passe par un objet Encoding, et c'est à ce stade que vit votre décision de jeu de caractères (on y revient plus bas). Ensuite, FromBase64String alloue un tableau neuf de la longueur exacte du décodage, vous ne traînez donc jamais de capacité en trop. Enfin, "TWFu" se décode en le mot « Man », trois octets, zéro surprise, ce qui en fait le test de fumée parfait pour n'importe quel code de décodage que vous écrirez.

Ce que le décodeur pardonne, ce qu'il refuse

C'est ici que le décodeur .NET a une personnalité, et un tempérament : il est généreux sur un point et impitoyable sur tous les autres. Ce sur quoi il est généreux, c'est l'espacement. Le décodeur saute exactement quatre caractères, où qu'ils apparaissent : l'espace (U+0020), la tabulation (U+0009), le saut de ligne (U+000A) et le retour chariot (U+000D). Cette politique est un clin d'œil délibéré à l'e-mail, où les payloads Base64 arrivent enveloppés dans de courtes lignes, et ça veut dire qu'une pièce jointe enveloppée au format MIME se décode sans aucun prétraitement. Un fait amusant : cette indulgence est partagée par toute la famille intégrée, y compris la classe basée sur les spans System.Buffers.Text.Base64 et la classe URL-safe Base64Url, vous obtenez donc le même comportement indulgent quel que soit l'API que vous choisissez. Tout ce qui sort de l'alphabet de 64 symboles, toute règle de longueur violée ou tout padding mal placé mérite une exception. Voici le même décodeur face à quelques entrées différentes :

Entrée Résultat
"TWFu" Se décode en Man (3 octets).
"TWF" + CRLF + "u" Se décode en Man. Les sauts de ligne au milieu sont invisibles pour le décodeur.
"TWFu" + espace insécable FormatException. Seuls les quatre caractères blancs ci-dessus sont sautés ; un espace insécable n'en fait pas partie.
"TWE" FormatException. Espaces mis à part, la longueur doit être un multiple de 4.
"TWFu=" FormatException. Le padding après la fin des données n'est pas autorisé.
"====" FormatException. Plus de deux caractères de padding est invalide.
"" ou seulement des espaces Un tableau d'octets vide. Un succès silencieux et valide.
"TW=u" FormatException. Un padding au milieu est invalide.

Le contrat honnête est donc petit et mémorable : une référence Nothing lève ArgumentNullException, une entrée vide ou uniquement espacée se décode en tableau vide, une entrée valide se décode en octets, et tout le reste d'invalide lève une exception bien précise, FormatException.

Des octets au texte : choisir le jeu de caractères

Dès que vous décidez que les octets décodés sont en fait du texte, vous devez nommer un jeu de caractères, parce que des octets ne sont du texte que lorsque vous dites comment les lire. Les chaînes Visual Basic sont du UTF-16 en interne, mais les octets qui sortent du décodeur ont été faits par quelqu'un d'autre, probablement selon un autre schéma, vous devez donc vous aligner sur leur choix. Le menu pratique :

  • Encoding.UTF8 : le défaut sûr pour tout ce qui a voyagé sur le web ou à travers une API. En cas de doute, commencez ici.
  • Encoding.Unicode : UTF-16 little-endian, la saveur native de .NET. Cohérent quand les deux côtés de l'échange sont des programmes .NET qui ont explicitement choisi UTF-16.
  • Encoding.ASCII : 7 bits seulement. Les octets non ASCII sont remplacés par un point d'interrogation, donc c'est un choix avec perte qui détruit les accents en silence.
  • Encoding.Default : sur .NET Framework c'était la page de codes ANSI de la machine, mais sur .NET (Core) c'est toujours de l'UTF-8, quel que soit le locale. Évitez-le quand même pour les données que vous échangez - nommez l'encodage explicitement, en général Encoding.UTF8.
Imports System
Imports System.Text
Module CharsetDemo
    Sub Main()
        ' Le mot "Café" stocké en octets UTF-8
        Dim bytes() As Byte = System.Convert.FromBase64String("Q2Fmw6k=")
        Dim correct As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(correct)
        ' Café
    End Sub
End Module

Lisez ces mêmes cinq octets avec Encoding.Unicode à la place et vous obtenez une courte chaîne de n'importe quoi - quelques caractères bizarres de la plage CJK plus un signe de remplacement - parce que le décodeur associe les octets deux par deux. Lisez les octets UTF-8 de « Café » avec Encoding.ASCII et l'accent devient ??, une paire de points d'interrogation, parce que l'accent fait deux octets en UTF-8. Aucun de ces choix ne lève d'exception ; ils produisent simplement du mauvais texte en silence, c'est pourquoi le jeu de caractères est une décision que vous prenez exprès, pas un défaut que vous héritez.

L'alphabet URL-safe : Base64Url

Le Base64 standard utilise + et /, et ces deux caractères portent chacun leur propre signification à l'intérieur des URL, si bien que l'alphabet standard peut casser un lien dès l'instant où il atterrit dans une chaîne de requête. La solution, standardisée dans la section 5 de la RFC 4648, est la variante sûre pour les URL et les noms de fichiers : le même schéma de 64 caractères avec - à la place de + et _ à la place de /, et avec le padding final typiquement abandonné, parce qu'il est implicite dans la longueur. Vous croiserez cet alphabet dans les JWT, les jetons d'API, et partout où le Base64 voyage à l'intérieur d'une URL. .NET 9 a ajouté une classe dédiée pour cela, System.Buffers.Text.Base64Url, et c'est un plaisir à utiliser :

Imports System.Buffers.Text
Imports System.Text
Module UrlSafeOpener
    Sub Main()
        ' Entrée URL-safe, sans padding à la fin
        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

Deux comportements méritent d'être connus. L'encodeur Base64Url produit en conception une sortie sans padding, mais son décodeur accepte à la fois les entrées avec et sans padding, il est donc accueillant envers les données d'autres écosystèmes. Et Base64Url.IsValid vous permet de pré-vérifier une chaîne candidate avant de décoder, ce qui est pratique quand les données viennent du monde extérieur. Si vous êtes bloqué sur un runtime plus ancien sans la classe, la conversion est deux échanges de caractères et un rattrapage de padding, exactement l'inverse de ce que faisait l'encodeur :

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

Sur .NET Framework 4.6.2 ou plus récent, vous pouvez à la place installer le paquet NuGet Microsoft.Bcl.Memory et utiliser la vraie classe Base64Url. Dans les deux cas, la règle est simple : reconnaissez l'alphabet à partir du contexte (URL, JWT, jeton d'API), puis choisissez le décodeur correspondant.

Ouvrir les fichiers

L'un des usages les plus anciens du Base64 est de faire passer du binaire par des fichiers texte : un fichier .b64 ou .txt qui contient des octets encodés. En Visual Basic, l'aller-retour fait deux appels fichiers et un décodage. Lisez le texte, décodez-le, écrivez les octets :

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

L'indulgence envers les espaces rend ceci robuste d'une façon satisfaisante : le fichier se moque que le payload ait été écrit en une seule longue ligne, enveloppé à 76 caractères, ou enveloppé à 64, parce que le décodeur saute les sauts de ligne dans tous les cas. Gardez un fait de dimensionnement dans votre poche : le fichier texte est à peu près un tiers plus gros que le binaire qu'il cache, donc un fichier de 10 méga-octets arrive sous forme d'environ 13,3 méga-octets de caractères. Rien de dramatique, mais c'est le chiffre à retenir quand un fichier texte « petit » semble grand.

Images et data URIs

Le schéma des data URIs (RFC 2397) permet à une URL de porter son propre contenu : data: suivi du type média, du marqueur littéral ;base64, d'une virgule, puis des octets encodés. Vous l'avez vu partout sur le web, dans le HTML et le CSS, où il intègre de petites images et des polices directement dans le balisage au lieu de pointer vers un fichier séparé. En Visual Basic, en déballer un ne fait qu'un découpage de chaîne et un décodage. L'exemple ci-dessous tire un PNG hors d'un data URI et en construit une image WPF :

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

Remarquez la vérification défensive sur l'en-tête : un data URI sans le marqueur ;base64 contient au contraire des données échappées pour l'URL, et les décoder comme du Base64 échouerait ou produirait du n'importe quoi. La RFC elle-même avertit que les data URIs ne sont utiles que pour des valeurs courtes, et le HTML a ses propres limites de longueur d'attribut, donc traitez ceci comme l'outil juste pour des icônes, des avatars et des vignettes, plutôt que pour expédier toute votre bibliothèque photo dans un seul attribut.

HTTP, API et authentification de base

Le Base64 est partout dans les API web, et les deux apparitions les plus courantes sont l'en-tête d'authentification HTTP de base et les champs JSON qui portent des données binaires ou pré-encodées. L'authentification de base est le cas le plus simple : le client envoie Authorization: Basic suivi du Base64 de username:password. Le décoder en Visual Basic, c'est une vérification de préfixe et un appel :

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

La fonction rend username:password en tant que chaîne unique, que vous découpez ensuite sur le deux-points. L'autre cas du quotidien est une réponse JSON où un champ est un blob pré-encodé, comme une image ou un certificat. Avec HttpClient et System.Text.Json (System.Text.Json est fourni d'office depuis .NET Core 3.0, et HttpClient bien avant), le schéma est simple :

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

Deux notes d'hygiène. N'imprimez jamais un identifiant décodé dans un journal ou une interface juste parce que vous le pouvez, et ne vous fiez jamais à l'authentification de base sur du HTTP en clair, parce que là vous n'avez fait qu'épeler le mot de passe dans un alphabet plus intéressant.

JWT : lire les trois morceaux

Un JSON Web Token sous sa forme compacte est trois morceaux de Base64Url séparés par des points : l'en-tête, le payload et la signature. Les deux premiers sont du JSON brut que vous pouvez lire de vos yeux (ou avec un appel de décodage), tandis que le troisième est une signature cryptographique qu'il faut vérifier avec la bonne clé, pas décoder. Un jeton d'exemple issu d'une démo courante a cette allure : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.W-5gI_FdnMBdpgG4twX96rptvh13gmXQ75kKLRXVaGs. Lire son payload en Visual Basic, c'est découper sur les points, convertir l'alphabet URL-safe de retour à l'alphabet standard, et décoder :

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
        ' Convertir l'alphabet URL-safe de retour à l'alphabet standard
        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

Exécutez ceci sur le jeton d'exemple et vous obtenez le JSON {"sub":"1234567890","name":"John Doe"}. Lisez l'en-tête de la même façon et vous obtenez {"alg":"HS256","typ":"JWT"}. L'avertissement qui compte ici : lire un JWT, ce n'est pas le vérifier. N'importe qui peut fabriquer un jeton, alors avant de faire confiance à une quelconque affirmation qu'il contient, validez la signature avec la clé de l'émetteur. Pour ce travail, le paquet NuGet System.IdentityModel.Tokens.Jwt (la suite IdentityModel de l'équipe Microsoft Entra) s'occupe des détails Base64Url, de la vérification de signature et de l'analyse des affirmations pour vous, c'est exactement la couche où vous ne voulez pas bricoler par vous-même.

Pièces jointes d'e-mail, enveloppées à 76 caractères

L'e-mail est l'endroit où le Base64 a gagné sa réputation. Le SMTP a été conçu pour l'ASCII 7 bits, donc une pièce jointe binaire doit devenir du texte avant de pouvoir s'envoler, et la norme MIME (RFC 2045) a choisi le Base64 avec une limite de ligne de 76 caractères, un proche cousin des lignes de 64 caractères, encore plus anciennes, du PEM. Si vous avez déjà reçu un e-mail brut, vous avez vu le résultat : un bloc de Base64 dense, coupé en petites lignes bien rangées, sous un en-tête Content-Transfer-Encoding: base64. La belle partie pour un décodeur, c'est qu'il n'a pas à défaire quoi que ce soit. Le décodeur .NET saute les sauts de ligne et les espaces où qu'ils apparaissent, donc le bloc enveloppé se décode tel quel :

Imports System
Imports System.Text
Module MimeOpener
    Sub Main()
        ' Une phrase de 59 octets, enveloppée au format MIME à 76 caractères avec 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

Si vous travaillez avec les classes System.Net.Mail, le décodage est encore plus invisible : une Attachment que vous ajoutez à une MailMessage porte un ContentEncoding de TransferEncoding.Base64, et la bibliothèque de courrier enveloppe, envoie et défait tout le rituel pour vous. Vous n'avez besoin du décodage manuel que lorsque vous lisez du MIME brut depuis un flux, un fixture de test ou un fichier de boîte aux lettres legacy.

Bases de données, configuration et variables d'environnement

Le stockage purement texte n'en finit pas de demander du Base64 : une colonne de base de données typée en texte, une valeur de configuration XML, une variable d'environnement. Tous veulent des caractères simples, donc le binaire s'encode avant d'être stocké et se décode à son retour. Le côté décodage est toujours le même one-liner, et la partie intéressante est le calcul de taille. Une colonne NVARCHAR classique de SQL Server plafonne à 8 000 caractères, ce qui veut dire environ 6 000 octets de binaire avant que la taxe de 33 pour cent ne vous pousse au-delà ; au-delà, on se tourne vers les variantes MAX ou, plus honnêtement, vers une vraie colonne binaire. Sur Windows, une seule variable d'environnement définie par l'utilisateur est plafonnée à 32 767 caractères (et sur les systèmes de l'ère XP, le bloc d'environnement entier plafonnait aussi à cette taille), donc « stocker tout le blob de licence dans une variable d'environnement » a un plafond dur. Voici un motif de décodage à garder dans un coin de la tête : vérifier une empreinte stockée contre un fichier, avec une comparaison à temps constant pour qu'une divergence ne fuite pas d'information temporelle :

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

La même forme fonctionne pour n'importe quel hachage stocké : décoder la valeur stockée, calculer le hachage frais, et comparer à temps fixe. Les fichiers de configuration suivent le motif identique, que la valeur vienne d'une entrée XML app.config, d'un fichier de paramètres JSON ou d'une chaîne du registre.

Gros volumes : décoder un flux sans le charger

Tous les exemples jusqu'ici ont lu le payload entier en mémoire, ce qui va bien pour des pièces jointes et des valeurs de configuration, mais pas pour un fichier de deux gigaoctets que quelqu'un a encodé dans un fichier texte. Pour cette échelle, .NET a une paire en flux qui existe depuis .NET Framework 1.1 (2003) : la transformation cryptographique FromBase64Transform enveloppée dans un CryptoStream. Vous lisez des blocs de texte encodé, la transformation les décode au vol, et vous écrivez les octets, la mémoire donc reste plate quel que soit le gabarit du fichier :

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

Parce que le fichier encodé est du texte ASCII ordinaire, le lire comme un flux d'octets est parfaitement sûr, et la transformation gère l'enveloppement des lignes sans que vous ne fassiez rien. Le fichier de sortie sort à peu près aux trois quarts de la taille de l'entrée, c'est la même taxe de 33 pour cent payée à l'entrée, encaissée à la sortie.

Les pièges qui mordent Visual Basic en particulier

La plupart des pièges de cette section sont partagés avec les autres langages .NET, mais quelques-uns portent un chapeau nettement VB, donc les voici ensemble :

  • Byte contre Byte(). En Visual Basic, un octet seul est Byte et un tableau d'octets est Byte(), les parenthèses vides faisant tout le travail. Écrire Dim b As Byte quand vous vouliez Byte() est l'erreur classique du premier jour, et c'est exactement le genre de chose que Option Strict On attrape à la compilation. Si votre projet ne l'a pas déjà activé, activez-le : le gabarit dotnet new console -lang VB vous laisse le choix, tandis que les gabarits de projet Visual Studio l'activent.
  • Le mur des spans. Les API modernes basées sur les spans sont appelables depuis le VB, mais uniquement au point d'appel : vous pouvez passer un tableau Byte() ou Char() directement dans une méthode qui prend un span, et le compilateur le convertit pour vous. Ce que vous ne pouvez pas faire, c'est nommer un span dans votre propre code. Déclarez une variable, un champ ou un paramètre de type Span ou ReadOnlySpan et le compilateur répond « Types with embedded references are not supported in this version of your compiler ». L'idiome VB est donc : appelez les API span avec des tableaux simples, et ne tentez jamais de stocker un span dans une variable.
  • BitConverter n'est pas du Base64. BitConverter.ToString(bytes) affiche les octets en hexadécimal, séparés par des tirets, ce qui en fait une fausse réponse séduisante pour quiconque a entendu « convertir des octets en chaîne ». Il vous remettra volontiers 4D-61-6E quand l'API attend TWFu. En cas de doute, prenez System.Convert.
  • MidB est un fantôme. Le Visual Basic classique avait des fonctions de chaîne au niveau de l'octet, MidB, LeftB et RightB, conçues pour les jeux de caractères à double octet. Toutes les chaînes .NET sont maintenant de l'Unicode, et la documentation du runtime est franche : elles ne sont plus prises en charge. Si un extrait legacy les utilise, réécrivez-le avec des tableaux d'octets et les API de cet article.
  • Encoding.Default suit la machine. L'histoire de la divergence selon le locale est celle du .NET Framework : sur .NET moderne, Default est toujours de l'UTF-8, donc les mêmes octets se décodent de la même façon partout. Pour les données que vous partagez, nommez l'encodage explicitement, en général Encoding.UTF8 - le conseil tient dans les deux cas.
  • Les allers-retours ne sont pas l'identité. Si vous décodez une chaîne puis ré-encodez le résultat, la nouvelle chaîne n'est pas garantie de correspondre à l'originale : les espaces disparaissent, et le padding est normalisé. Un payload avec des sauts de ligne revient en une seule ligne propre. Parfait pour les données, dangereux si votre logique compare le texte encodé au lieu des octets décodés.
  • Une entrée d'espaces seulement est un succès silencieux. Une chaîne d'espaces et de sauts de ligne uniquement se décode en tableau d'octets vide sans aucune erreur, ce qui veut dire que « l'utilisateur a collé que des retours à la ligne » a exactement le même air que « l'utilisateur a collé un payload vide ». Si la distinction compte, vérifiez la longueur de l'entrée avant de décoder.

Bonnes pratiques pour le décodage

Distillé de tout ce qui précède, voici les habitudes qui gardent le code de décodage ennuyeux (dans le meilleur sens) :

  • Traitez le Base64 comme un transport, pas comme une protection. C'est un encodage, pas un chiffrement : n'importe qui peut lire l'original avec un appel de fonction, et la RFC 4648 note même qu'un traitement mal soigné de l'alphabet peut ouvrir des canaux couverts. Chiffrez d'abord, puis encodez si vous devez cacher du contenu.
  • Pour une entrée non fiable, préférez les méthodes Try ou une pré-vérification IsValid plutôt que de laisser FormatException voler. Un booléen se transforme plus facilement en message d'erreur amical qu'une exception ne se laisse avaler.
  • Choisissez le jeu de caractères exprès, et partez de l'UTF-8 par défaut sauf si vous avez une raison documentée pour un autre schéma.
  • Adaptez l'alphabet à la source : Base64 standard pour le MIME, l'e-mail et la configuration ; Base64Url pour les JWT et tout ce qui est à l'intérieur d'une URL.
  • Faites passer tout ce qui est grand en flux par FromBase64Transform et CryptoStream au lieu de le charger dans une chaîne.
  • Comparez les empreintes et les hachages avec CryptographicOperations.FixedTimeEquals, pas avec =, pour que le temps ne fuite pas combien de la valeur correspondait.
  • Gardez Option Strict On pour que la famille des glissements Byte/Byte() soit une erreur de compilation plutôt qu'un mystère en production.

Comment Visual Basic a obtenu son décodeur

L'histoire commence à une époque où Visual Basic n'avait pas de Base64 du tout. Dans le monde de Visual Basic 6 et du VBA (le langage de macros qui tourne encore aujourd'hui dans Excel et Office), les développeurs qui avaient besoin de Base64 l'empruntaient aux composants COM déjà sur la machine. Le coup célèbre utilisait un élément XML DOM : l'analyseur MSXML laisse un nœud déclarer son DataType comme bin.base64, donc assigner une chaîne Base64 à la propriété text du nœud et relire son nodeTypedValue vous remet les octets bruts, le DOM faisant le vrai calcul Base64 (la propriété Charset de l'objet Stream ADO ne comprend que de vrais noms de jeu de caractères comme « utf-8 » ou « iso-8859-1 », pas « base64 », c'est pourquoi le coup va chercher MSXML à la place). L'encodage jouait la même idée en sens inverse, écrivant les octets dans nodeTypedValue et relisant la chaîne encodée hors de text :

' Le coup classique de décodage VB6 / VBA, pour le contexte
Dim node As Object
Set node = CreateObject("MSXML2.DOMDocument").createElement("b64")
node.DataType = "bin.base64"
node.text = packed            ' la chaîne Base64
Dim bytes() As Byte
bytes = node.nodeTypedValue

Ça marchait, c'était malin, et c'est la raison pour laquelle « base64 VBA » fait encore s'allumer les moteurs de recherche trois décennies plus tard. Puis 2002 a tout changé : Visual Basic 7.0 (la première version .NET du langage, alors appelée Visual Basic .NET) a rejoint le nouveau Common Language Runtime, et le .NET Framework a apporté System.Convert avec FromBase64String et ses amis, prêt à l'emploi. Dès .NET Framework 1.1 en 2003, chaque programme VB avait un décodeur de premier ordre, sans aucun composant à enregistrer. La vague moderne est arrivée en 2018 avec .NET Core 2.1, qui a ajouté les méthodes Try sans exceptions et la classe rapide basée sur les spans System.Buffers.Text.Base64, puis en 2024 avec .NET 9, qui a enfin standardisé l'alphabet URL-safe sous le nom de Base64Url. En 2026, .NET 10 - sorti en novembre 2025 - est la version de support à long terme, et les bibliothèques .NET 11 en aperçu ajoutent une nouvelle génération de méthodes de confort Base64, donc le décodeur ne cesse de s'améliorer, même si le one-liner original de 2003 continue sans changer.

Faits amusants du monde VB

  • Le compilateur officiel de Visual Basic est lui-même écrit en Visual Basic. Dans le cadre du projet open source Roslyn, le langage se compile lui-même.
  • Le tout premier Visual Basic est sorti en 1991, avant que l'ère du web ne s'installe. Le grand moment du Base64 est arrivé avec le MIME en 1993, et le VB lui-même a grandi d'une capacité 32 bits deux ans plus tard, quand Visual Basic 4 en 1995 a rendu les programmes 32 bits possibles pour la première fois. VB 5 en 1997 est allé jusqu'au bout : 32 bits seulement, plus aucun 16 bits dans la boîte.
  • Les fonctions au niveau de l'octet MidB, LeftB et RightB du VB classique sont officiellement « plus prises en charge » sous .NET, parce que chaque chaîne VB est de l'Unicode depuis le premier jour du framework. Toute une famille d'API, à la retraite par un choix d'encodage.
  • La machinerie Base64 du runtime n'est pas une vieille table de consultation : l'implémentation moderne exécute des chemins de code vectorisés par le matériel (variantes AVX-512, AVX2 et SSE) quand la machine les supporte, donc « lent codec texte » n'est pas ce qui se passe sous le capot.
  • Le coup MSXML bin.base64 de l'ère VB6 tourne encore aujourd'hui dans des macros Excel de production, ce qui veut dire qu'un palliatif de la fin des années 1990 et un appel Convert de 2003 coexistent joyeusement dans la base de code du même organisme.

Avant de partir

Cet article a couvert le côté décodage du Base64 en Visual Basic, du one-liner au flux, des JWT aux pièges qui portent un chapeau VB. L'autre moitié de la pièce, transformer vos octets et votre texte en Base64 en premier lieu, a son propre lot de décisions sur le padding, les sauts de ligne et la taxe de taille, et elle est traitée en détail complet dans l'article compagnon d'encodage sur le site sœur. Le lien vers lui est juste en dessous de cette ligne, et l'outil de la page d'accueil reste le moyen le plus rapide de vérifier un petit payload à la main.

Dernière mise à jour : 2026-09-08

Article associé : Encodage Base64 en Visual Basic : un guide complet