Encodage Base64 en Visual Basic : un guide complet
Voici un problème que les développeurs Visual Basic croisent depuis vingt-cinq ans : vous avez un JPEG, un blob binaire, un fichier de licence ou une phrase parfaitement ordinaire, et le canal devant vous n'accepte que du texte. Un champ JSON, une variable d'environnement, une pièce jointe d'e-mail, une URL, un fichier de configuration, une colonne de base de données typée en texte, et toutes les autres portes de l'immeuble ont une règle en commun : des caractères imprimables uniquement. Le Base64 est le gardien de la porte qui laisse entrer le binaire. Il réécrit vos octets en un flux de lettres, chiffres, plus, barres obliques et signes égaux, si bien que tout ce qui voyage sous forme de texte peut les porter. Et la bonne nouvelle : chaque morceau d'encodeur dont vous pourriez avoir besoin est déjà dans le runtime .NET. Ni paquets, ni composants, ni cérémonie.
En un souffle, parce que la page d'accueil de ce site creuse le format lui-même : le Base64 prend trois octets en entrée et les écrit sous forme de quatre caractères d'un alphabet de 64 symboles, en ajoutant un ou deux caractères = à la queue quand le nombre d'octets ne se divise pas exactement. Cet échange de quatre pour trois, c'est pourquoi les données encodées tournent à peu près un tiers au-dessus de l'original, la fameuse taxe de taille que vous payez une fois par encodage. Tout le reste de cet article consiste à faire en sorte que l'encodage que vous produisez fasse exactement ce que le système suivant attend : le bon alphabet, le bon padding, les bons sauts de ligne, et le bon jeu de caractères.
La boîte à outils de l'encodeur : tout est intégré
Le côté encodage du runtime s'est agrandi sur les mêmes quatre vagues que le côté décodage, donc la boîte à outils a une longue traîne d'options encore prises en charge. Voici la famille complète et la mission pour laquelle chacune est faite :
| API | Disponible depuis | À quoi ça sert |
|---|---|---|
System.Convert.ToBase64String |
.NET Framework 1.1 (2003) | Le classique. Un tableau en entrée, une chaîne en sortie, avec des surcharges pour les tranches de tableau, les spans et des sauts de ligne façon MIME optionnels. |
System.Convert.ToBase64CharArray |
.NET Framework 1.1 (2003) | Écrit les caractères encodés dans un tampon de caractères que vous avez déjà alloué, et renvoie combien de caractères il a utilisés. |
System.Convert.TryToBase64Chars |
.NET Core 2.1 (2018) | Encodage basé sur les spans et léger en allocation, dans un span de caractères que vous fournissez, avec une réponse booléenne au lieu d'une exception. |
System.Buffers.Text.Base64 |
.NET Core 2.1 (2018) | Encodage bas niveau, basé sur les spans : écrivez dans votre propre tampon UTF-8, gonflez in place, et dimensionnez les tampons avec GetMaxEncodedToUtf8Length. |
System.Buffers.Text.Base64Url |
.NET 9 (2024) | L'alphabet URL-safe (- et _ au lieu de + et /) sans padding. Sur les runtimes plus anciens, il voyage dans le paquet NuGet Microsoft.Bcl.Memory. |
ToBase64Transform + CryptoStream |
.NET Framework 1.1 (2003) | L'encodage en flux : lisez un fichier en blocs, écrivez le texte encodé, gardez la mémoire plate sur les entrées géantes. |
Pour le paysage des versions : .NET 10 est la version de support à long terme actuelle (novembre 2025, support jusqu'en novembre 2028), .NET 8 et .NET 9 sont pris en charge jusqu'en novembre 2026, et .NET 11 est en aperçu avec un lot de nouvelles méthodes de confort Base64 en route. Tout ce qui figure dans le tableau ci-dessus est stable sur toutes ces versions. La seule porte de version est Base64Url : intégrée à partir de .NET 9, disponible sur .NET Framework 4.6.2 et plus récent via le paquet Microsoft.Bcl.Memory, et c'est le seul paquet que cet article vous demande jamais d'installer. Pour lancer un projet jetable, le SDK .NET fournit Visual Basic en standard :
dotnet new console -lang VB -o Packer
cd Packer
dotnet run
Votre premier encodage : octets en entrée, texte en sortie
Quatre-vingt-dix pour cent de la vie de l'encodage en Visual Basic tiennent dans deux appels, et l'ordre compte : l'encodeur prend des octets, pas du texte, donc si vous partez d'une chaîne, vous choisissez d'abord un encodage pour la transformer en octets, et seulement ensuite vient l'étape Base64. Voici toute la danse :
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
Cette section médiane de trois lignes est tout l'art, et la chaîne "TWFu" est le test de fumée parfait pour n'importe quel encodeur que vous écrivez. Les surcharges vous donnent du contrôle quand vous en avez besoin. Les formes en tranche encodent un morceau de tableau sans le copier d'abord, ce qui est pratique quand le vrai payload se trouve dans un tampon plus grand :
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== (seuls les octets 3 à 6 ont été encodés)
End Sub
End Module
Et la forme tableau-vers-caractères, ToBase64CharArray, écrit dans un tampon de caractères que vous allouez et vous dit combien de caractères il a remplis, c'est le bon outil quand la destination fait partie d'une structure de texte plus grande que vous construisez à la main. Notez la règle de maison pour la syntaxe Visual Basic : un tableau d'octets s'écrit Byte() avec les parenthèses vides. Omettez-les et vous avez un octet seul, et Option Strict On (désactivé par défaut dans les gabarits - à activer dans chaque projet) attrapera la confusion à la compilation.
Façonner la sortie : padding, sauts de ligne et tailles exactes
Encoder deux fois les mêmes octets peut légitimement produire deux chaînes différentes, et les différences tiennent toutes à la façon de façonner la sortie. D'abord, le padding : quand la longueur de l'entrée n'est pas un multiple de trois, l'encodeur complète le groupe final avec un ou deux caractères =. La RFC dit de les inclure sauf si la norme que vous suivez dit le contraire, et ToBase64String les inclut par défaut. Ensuite, les sauts de ligne : le second paramètre des surcharges de mise en forme, Base64FormattingOptions.InsertLineBreaks, fait émettre à l'encodeur des lignes de 76 caractères séparées par CRLF, c'est exactement la règle MIME. Le MIME lui-même utilise une limite de 76 caractères, un proche cousin des vieilles lignes de 64 caractères du PEM, et les deux limites remontent à des restrictions à l'intérieur du SMTP. Si votre consommateur est un pipeline d'e-mail, activez les sauts de ligne ; si c'est une URL, un champ JSON ou une colonne de base de données, laissez-les désactivés, parce qu'un CRLF invisible dans vos données trouvera toujours un moyen de vous surprendre plus tard :
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 : deux lignes de 76 caractères plus un CRLF entre les deux
End Sub
End Module
Enfin, les tailles exactes, parce que vous voudrez pré-allouer des tampons et des largeurs de colonnes. La règle est quatre caractères pour chaque groupe de trois octets en entrée, arrondi par excès : 1000 octets deviennent 1336 caractères. Plutôt que de faire l'arithmétique à la main, le runtime a un helper qui renvoie la longueur encodée maximale pour une taille d'entrée donnée, c'est ce que vous passez à l'allocation du tampon :
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
Ce même ratio de quatre pour trois est la taxe de taille dans sa forme la plus pure : chaque valeur encodée est à peu près 33 pour cent plus grande que les octets qu'elle porte, donc planifiez vos tailles de stockage et de transfert avec cette marge en tête. Et un comportement à connaître avant qu'il ne vous morde : 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, parce que les espaces disparaissent et que le padding se normalise. Comparez des octets décodés quand vous devez comparer des valeurs, pas le texte encodé.
Choisir le jeu de caractères avant d'encoder
Parce que la première étape de l'encodage de texte est « chaîne vers octets », le jeu de caractères que vous choisissez décide de ce que le destinataire verra quand il décode. Les chaînes Visual Basic sont du UTF-16 dans le runtime, mais les octets que vous émettez devraient correspondre à ce que l'autre côté attend de lire, et le menu des choix est court :
Encoding.UTF8: le défaut juste pour le web, les API et tout ce qui est moderne. Il fait l'aller-retour de chaque caractère Unicode que le langage peut contenir.Encoding.Unicode: UTF-16 little-endian. Un choix cohérent quand les deux extrémités du tuyau sont des programmes .NET qui ont explicitement convenu de l'UTF-16, et rien de plus.Encoding.ASCII: 7 bits seulement, et il remplacera silencieusement tout le reste par un point d'interrogation. Encoder « Café » en ASCII vous donne les octets de « Caf? », qui se décodera exactement ainsi, point d'interrogation compris.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 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== (l'accent est devenu un point d'interrogation)
End Sub
End Module
Deux chaînes Base64 différentes, un mot, et seulement l'une des deux survit au voyage. La règle pratique : à moins que le protocole que vous suivez ne nomme un autre schéma, encodez le texte en UTF-8 et dites-le.
Base64Url : l'alphabet qui survit aux URL
L'alphabet standard contient + et /, et ces deux caractères ont chacun leur propre rôle à l'intérieur des URL, donc le Base64 bâti sur cet alphabet casse dès l'instant où il atterrit dans une chaîne de requête ou un segment de chemin. La solution, standardisée dans la section 5 de la RFC 4648, échange les deux fautifs contre - et _, qui sont sûrs pour les URL, et abandonne habituellement le padding final, parce que la longueur des données dit déjà au décodeur où elles finissent. Cette variante, connue sous le nom de base64url, est l'alphabet des JWT, des jetons d'API et d'un nombre croissant d'API. .NET 9 a ajouté une classe dédiée pour elle, et elle est construite avec une opinion qui mérite d'être connue : elle omet le padding par conception :
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 (tiret bas, sans padding final)
End Sub
End Module
L'exemple ci-dessus est un bon choix : les octets choisis font apparaître l'un des caractères spéciaux - le tiret bas, là où l'alphabet standard a une barre oblique - vous pouvez donc voir l'échange se produire. Quand vous êtes sur un runtime plus ancien, le même alphabet, c'est deux remplacements de caractères plus un nettoyage, et vous obtenez un résultat compatible en direct :
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
Sur .NET Framework 4.6.2 ou plus récent, le paquet Microsoft.Bcl.Memory vous donne à la place la vraie classe Base64Url. Dans les deux cas, attention à la ligne de partage sur le padding : la sortie Base64Url de .NET n'a pas de padding, tandis que certaines bibliothèques d'autres écosystèmes l'ajoutent (et quelques décodeurs stricts l'exigent). Le JWT, par exemple, exige la forme sans padding, donc le défaut de .NET est pile juste là. Quand vous traversez une frontière d'écosystème, vérifiez l'attente de l'autre côté avant d'envoyer la chaîne.
Emballer les fichiers
Les fichiers sont le cas d'usage original : transformer un fichier binaire en fichier texte que l'e-mail, le FTP et les systèmes de configuration porteront tous avec plaisir. En Visual Basic, tout le travail tient en trois appels, dont un qui lit et un qui écrit :
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
Gardez le ratio de taille en poche : une photo de 10 méga-octets devient un fichier texte d'environ 13,4 méga-octets. L'opération est rapide sur du matériel moderne (on y revient plus bas), donc le coût est presque toujours le stockage et la bande passante plutôt que le processeur, c'est la facture habituelle d'une taxe de 33 pour cent. Quand le fichier ne vivra qu'à côté du texte qui y fait référence, ce motif va parfaitement ; quand le fichier est grand et longévif, demandez-vous si le canal a vraiment besoin de la forme texte.
Images : construire des data URIs à la main
Le schéma des data URIs (RFC 2397) intègre le contenu d'un fichier directement dans une URL : data:, le type média, le marqueur littéral ;base64, une virgule, et les octets encodés. Les navigateurs les utilisent pour intégrer de petites images et des polices en ligne. WPF ne peut pas consommer un data URI directement - BitmapImage n'a pas de gestionnaire pour le schéma data: - donc le geste idiomatique est d'ôter le préfixe et de remettre les octets à un MemoryStream. Construire l'URI en Visual Basic, c'est une concaténation de chaînes, et le consommer, c'est un petit bloc d'initialisation :
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()
' l'image peut maintenant être assignée à un contrôle Image
End Sub
End Module
La RFC elle-même avertit que les data URIs ne sont utiles que pour des valeurs courtes, et les documents HTML imposent leurs propres limites de longueur d'attribut, donc le champ raisonnable est les icônes, les avatars, les vignettes et les petits motifs de fond. Le type média doit correspondre aux octets que vous avez réellement encodés, parce que rien en aval ne le ré-établira à partir du contenu.
HTTP : en-têtes d'authentification et payloads JSON
Sur le fil, les deux endroits où vous encodez à la main 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 la plus visible : l'en-tête est le mot Basic, un espace, et le Base64 de username:password joint par un deux-points. Le construire, c'est un appel d'encodage :
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
Le cas JSON est tout aussi routinier. Si une API veut une image ou un certificat dans le corps d'une requête, vous encodez les octets et glissez la chaîne dans le payload, et System.Text.Json (fourni d'office depuis .NET Core 3.0) gère la sérialisation autour :
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
Deux règles de maison : envoyez les identifiants uniquement sur HTTPS, parce que sur du HTTP en clair, le Base64 est un costume, pas un cadenas, et ne journalisez jamais l'en-tête d'authentification brut ni les identifiants auxquels il se décode.
Pièces jointes d'e-mail et enveloppement MIME
L'e-mail est là que le Base64 a gagné sa vie. Le SMTP a été bâti 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 fait le choix : Base64, enveloppé à 76 caractères par ligne, déclaré avec un en-tête Content-Transfer-Encoding: base64. Si vous travaillez avec les classes System.Net.Mail, tout le rituel tient en deux lignes de préparation, parce que la bibliothèque de courrier fait l'enveloppement pour vous à l'envoi :
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
Vous n'avez besoin de produire vous-même la forme enveloppée, avec Base64FormattingOptions.InsertLineBreaks, que lorsque vous écrivez du texte MIME brut à la main : un fixture de test de messagerie, une passerelle legacy, ou un outil qui crache des fichiers .eml. La règle des 76 caractères n'est pas une préférence de style ; certains systèmes récepteurs tronquent les lignes plus longues, c'est pourquoi la limite a survécu dans la norme depuis des décennies.
Stocker des valeurs encodées : bases de données, fichiers de 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. Vous encodez les octets, stockez la chaîne, et la décodez à la sortie. Le côté encodage est toujours le même one-liner, mais le côté stockage a des limites qui rendent la taxe de taille concrète. Une colonne VARCHAR classique de SQL Server s'arrête à 8 000 caractères (une colonne NVARCHAR s'arrête à la moitié, 4 000 caractères, parce que chaque caractère Unicode coûte deux octets) - 8 000 caractères, c'est de la place pour environ 6 000 octets de binaire avant que la surcharge de 33 pour cent ne vous pousse au-delà, au-delà de quoi on se tourne vers les types 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 « garder tout le blob de licence dans une variable d'environnement » a un plafond dur :
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
Les fichiers de configuration suivent la même forme, avec la valeur qui vit dans du texte XML ou JSON et le décodage qui a lieu dans votre code de démarrage. Une note legacy pour le coin entreprise : WCF et les contrats de données XML sérialisent un tableau d'octets sous le type de schéma XML base64Binary, donc un large corpus de services .NET plus anciens stocke le binaire exactement ainsi, et la valeur que vous trouverez dans ce XML est de la sortie ToBase64String ordinaire.
JWT : construire la forme compacte
Un JSON Web Token sous forme compacte est trois morceaux de base64url séparés par des points : l'en-tête, le payload et une signature. Les deux premiers sont du JSON brut, et le troisième est une preuve cryptographique que le porteur de la bonne clé a fabriqué ce jeton. Construire la forme non signée à la main, c'est deux encodages et une concaténation de chaînes, mais un JWT réel a besoin de l'étape de signature, et un petit exemple HMAC-SHA256 rend tout ça concret :
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
Exécutez avec l'en-tête {"alg":"HS256","typ":"JWT"} et un payload de votre choix, et le résultat est un vrai JWT compact : aucun padding nulle part, des caractères sûrs pour les URL dans les trois parties. Remarquez que la signature est du base64url aussi, parce que le jeton entier doit survivre à une URL ou à un en-tête HTTP. Pour les systèmes de production, le paquet System.IdentityModel.Tokens.Jwt (la suite IdentityModel de l'équipe Microsoft Entra) construit, signe et vérifie ces jetons pour vous, c'est la couche où vivent la gestion des clés, le verrouillage de l'algorithme et les vérifications d'expiration. Bricoler l'encodage à la main va bien pour comprendre et pour de petits outils ; pour tout ce qui garde un accès, laissez la bibliothèque porter le poids.
Pièges : là où les encodeurs VB trébuchent
Les pièges ici sont un mélange d'habitudes de langage et de surprises de mise en forme de sortie, et la plupart coûtent une session de débogage plutôt qu'un crash :
- Byte contre Byte(). L'encodeur veut un tableau. En Visual Basic, un octet seul est
Byteet un tableau estByte(), et la différence tient à une paire de parenthèses. SousOption Strict On, un mauvais choix est une erreur de compilation ; avec le strict désactivé, vous risquez au contraire une surprise à l'exécution. Gardez la stricte activée et les parenthèses visibles. - Le piège Encoding.Default, en sens inverse. L'histoire de la divergence selon le locale est celle du .NET Framework : sur .NET moderne,
Defaultest toujours de l'UTF-8, donc la même chaîne s'encode de la même façon sur chaque machine. Pour tout ce qui traverse des machines, nommez l'encodage explicitement, en général UTF-8 - le conseil tient dans les deux cas. - Le CRLF trouve toujours un chemin.
InsertLineBreaksest merveilleux pour le MIME et affreux pour les URL, le JSON et les colonnes texte de base de données, où il insère un retour chariot et un saut de ligne que personne n'a demandés. Utilisez-le seulement quand le consommateur attend des lignes enveloppées, et en cas de doute, utilisez le défautNone. - Décalages de padding à la frontière. Le
Base64Urlde .NET n'émet aucun padding, tandis que certaines bibliothèques d'autres écosystèmes l'ajoutent (et quelques décodeurs stricts l'exigent). Quand votre valeur encodée traverse un écosystème, confirmez l'attente de l'autre côté avant d'envoyer la chaîne ; le JWT veut la forme sans padding, c'est le défaut de .NET. - Les allers-retours ne sont pas l'identité. Décodez une chaîne enveloppée et padée, puis ré-encodez, et vous obtenez une ligne propre unique avec un padding neuf, pas le texte d'origine. Si votre logique compare des valeurs encodées à l'égalité, comparez les octets décodés à la place.
- Le plafond de taille est réel. La formule de longueur de sortie, quatre caractères par trois octets arrondi par excès, déborde un compteur sur 32 bits à peu près à 1,5 gigaoctet d'entrée, et l'encodeur répond par une
OutOfMemoryExceptionplutôt que par une chaîne partielle. Pour des entrées proche de cette échelle, passez en flux à la place (plus bas). - Le mur des spans. Les encodeurs basés sur les spans sont appelables depuis le VB au point d'appel : passez vos tableaux
Byte()ouChar()directement dedans et le compilateur les convertit. Mais vous ne pouvez pas déclarer une variable, un champ ou un paramètre de typeSpanouReadOnlySpan; le compilateur refuse avec « Types with embedded references are not supported in this version of your compiler ». L'idiome VB est d'appeler les API span avec des tableaux simples et de ne jamais stocker un span. - BitConverter n'est pas du Base64.
BitConverter.ToString(bytes)affiche l'hexadécimal avec des tirets entre les paires, donc c'est une fausse réponse séduisante qui produit4D-61-6Elà où l'autre système attendTWFu. Pour le Base64, la classe estSystem.Convert, à chaque fois.
Vitesse et taille : notes de performance
La réputation de « lent codec texte » du Base64 ne survit pas au contact du runtime moderne. L'encodeur dans .NET exécute du code vectorisé par le matériel quand la machine le supporte, avec des chemins rapides dédiés pour les jeux d'instructions AVX-512, AVX2 et SSE, et le chemin AVX-512 mâche 48 octets par étape. Pour des payloads ordinaires, l'appel classique ToBase64String est assez rapide pour que l'algorithme soit rarement le goulot d'étranglement ; les coûts que vous sentez sont la taxe de taille de 33 pour cent et, pour les chemins chauds, les allocations intermédiaires. Si vous encodez des millions de petites valeurs, les API basées sur les spans sont le raffinement : TryToBase64Chars écrit dans un span de caractères que vous contrôlez et signale le succès avec un booléen, et System.Buffers.Text.Base64 va plus loin, en codant directement dans des tampons UTF-8 que vous allouez et en gonflant même les données in place :
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
Le motif à remarquer est que vous dimensionnez le tampon avec le helper, y encodez, et ne convertissez en chaîne que le préfixe utilisé, ce qui garde la surface intermédiaire aussi petite que possible. Et pour les fichiers assez grands pour que les chaînes deviennent inconfortables, la paire en flux garde la mémoire plate : la transformation ToBase64Transform enveloppée dans un CryptoStream lit votre entrée en blocs et écrit le texte encodé, donc un fichier de deux gigaoctets n'a jamais à devenir une chaîne de 2,7 gigaoctets d'un seul tenant :
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
Une note vers l'avant : les bibliothèques .NET 11 en aperçu ajoutent de nouvelles surcharges de confort et de span aux types Base64 existants, donc si votre projet peut suivre les aperçus, la boîte à outils continue de grossir ; si ce n'est pas le cas, tout ce qui précède est stable sur chaque version prise en charge.
Une brève histoire : de MSXML aux spans
Bien avant .NET, les programmes Visual Basic qui avaient besoin de Base64 l'empruntaient au monde COM. Le coup classique VB6 et VBA (le langage de macros qui tourne encore dans Excel et Office) utilisait à la place un élément XML DOM : l'analyseur MSXML laisse un nœud déclarer son DataType comme bin.base64, donc écrire vos octets dans le nodeTypedValue du nœud et relire sa propriété text vous remet la chaîne encodée, 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 », donc elle ne joue aucun rôle dans la conversion elle-même). C'était malin, c'était partout, et c'est pourquoi « base64 VBA » fait encore s'allumer les moteurs de recherche des décennies plus tard. L'ère s'est terminée en 2002, quand la première version .NET du langage, Visual Basic 7.0, a rejoint le nouveau Common Language Runtime, et le .NET Framework a apporté System.Convert avec ToBase64String, prêt à l'emploi. Dès .NET Framework 1.1 en 2003, chaque programme VB pouvait encoder du Base64 avec un appel et aucun composant à enregistrer.
Les chapitres modernes sont courts. En 2018, .NET Core 2.1 a ajouté la méthode légère en allocation TryToBase64Chars et la classe bas niveau basée sur les spans System.Buffers.Text.Base64. En 2024, .NET 9 a standardisé l'alphabet URL-safe sous le nom de Base64Url, mettant fin à une décennie d'appels Replace bricolés à la main. En 2026, .NET 10 - sorti en novembre 2025 - est la version de support à long terme qui porte tout ça, et les bibliothèques .NET 11 en aperçu ajoutent une nouvelle génération de méthodes de confort, donc l'encodeur, du one-liner de 2003 à l'ère des spans, est l'histoire de la même classe qui devient plus rapide et plus précise, jamais une histoire de repartir de zéro.
Faits amusants, édition VB
InsertLineBreaksreproduit exactement la règle MIME des 76 caractères, CRLF compris, ce qui veut dire que les sauts de ligne que votre encodeur écrit en 2026 ont la même forme, octet pour octet, que ceux qu'une norme d'e-mail a définis dans les années 1990.- L'opérateur
IsNot, ajouté avec Visual Basic 2005, a fait une fois les actualités en tant qu'objet d'une demande de brevet Microsoft. Très peu d'opérateurs de langage peuvent réclamer cette distinction. - Le tout premier Visual Basic est sorti en 1991, avant que le World Wide Web n'existe. Au moment où le schéma des data URIs est apparu en 1998, le Base64 portait déjà des pièces jointes d'e-mail depuis cinq ans, et le VB était devenu un langage 32 bits trois ans avant cela, avec Visual Basic 4 en 1995.
- Sur du matériel avec AVX-512, l'encodeur du runtime traite 48 octets par étape vectorielle, c'est la différence entre une table de consultation dans un musée et un convoyeur dans une usine.
- L'espace de noms
My, la célèbre couche de sucre de Visual Basic depuis 2005, n'a jamais eu besoin d'ajouter un helper Base64.System.Convertn'a jamais été qu'à un import d'espace de noms, un cas rare où le runtime VB n'a rien ajouté à une histoire que le framework racontait déjà.
L'autre face
Cet article a couvert le côté encodage du Base64 en Visual Basic : la boîte à outils, les décisions de mise en forme de sortie, l'alphabet URL-safe, et les cas d'usage des fichiers aux JWT. La direction inverse, prendre une chaîne entrante et la ramener aux octets qu'elle cache, a son propre lot de comportements, de règles d'indulgence et de pièges, et elle est traitée en détail complet dans l'article compagnon de décodage 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 d'encoder un petit payload à la main.
Dernière mise à jour : 2026-09-08
Article associé : Décodage Base64 en Visual Basic : un guide complet