¿Tiene que ocuparse del formato Base64? Entonces esta página es perfecta para Ud. Utilice nuestra práctica herramienta en línea para codificar o decodificar sus datos.

Codificación Base64 en Visual Basic: una guía completa

Aquí tienes un problema con el que los desarrolladores de Visual Basic llevan topándose veinticinco años: tienes un JPEG, un blob binario, un archivo de licencia o una frase perfectamente corriente, y el canal que tienes delante solo acepta texto. Un campo JSON, una variable de entorno, un adjunto de email, una URL, un archivo de configuración, una columna de base de datos de tipo texto y todas las demás puertas del edificio comparten una regla: solo caracteres imprimibles. El Base64 es el portero que deja entrar al binario. Reescribe tus bytes como un stream de letras, dígitos, más, barra e iguales, así que todo lo que viaja como texto puede cargarlos. Y la buena noticia: cada pieza del codificador que puedas necesitar ya está dentro del runtime de .NET. Sin paquetes, sin componentes, sin ceremonia.

De un solo aliento, porque la página de inicio de este sitio profundiza en el formato en sí: Base64 toma tres bytes de entrada y los escribe como cuatro caracteres de un alfabeto de 64 símbolos, añadiendo uno o dos caracteres = al final cuando el recuento de bytes no se divide exactamente. Ese intercambio de cuatro por tres es la razón por la que los datos codificados corren un tercio más gordos que el original, el famoso impuesto de tamaño que pagas una vez por codificación. Todo lo demás de este artículo va de lograr que la codificación que produzcas haga exactamente lo que el siguiente sistema espera: el alfabeto correcto, el padding correcto, los saltos de línea correctos y el charset correcto.

La caja de herramientas del codificador: todo está integrado

El lado de codificación del runtime creció en las mismas cuatro oleadas que el de decodificación, así que la caja de herramientas tiene una larga cola de opciones aún soportadas. Aquí está la familia completa y el trabajo para el que cada una está hecha:

API Disponible desde Para qué sirve
System.Convert.ToBase64String .NET Framework 1.1 (2003) El clásico. Entra un array, sale una cadena, con sobrecargas para subconjuntos de array, spans y saltos de línea estilo MIME opcionales.
System.Convert.ToBase64CharArray .NET Framework 1.1 (2003) Escribe los caracteres codificados en un buffer de caracteres que ya asignaste, y devuelve cuántos caracteres usó.
System.Convert.TryToBase64Chars .NET Core 2.1 (2018) Codificación basada en spans, con poca asignación, en un span de caracteres que tú proporcionas, con una respuesta booleana en vez de una excepción.
System.Buffers.Text.Base64 .NET Core 2.1 (2018) Codificación de bajo nivel, basada en spans: escribe en tu propio buffer UTF-8, infla in place y dimensiona buffers con GetMaxEncodedToUtf8Length.
System.Buffers.Text.Base64Url .NET 9 (2024) El alfabeto URL-safe (- y _ en vez de + y /) sin padding. En runtimes más antiguos viaja en el paquete NuGet Microsoft.Bcl.Memory.
ToBase64Transform + CryptoStream .NET Framework 1.1 (2003) Codificación por streaming: lee un archivo en trozos, escribe texto codificado y mantiene la memoria plana con entradas gigantescas.

Por el panorama de versiones: .NET 10 es la release actual de soporte a largo plazo (noviembre de 2025, soportada hasta noviembre de 2028), .NET 8 y .NET 9 están soportadas hasta noviembre de 2026, y .NET 11 está en vista previa con un fresco lote de métodos cómodos de Base64 en camino. Todo lo de la tabla de arriba es estable en todas esas. La única puerta de versión es Base64Url: integrada desde .NET 9 en adelante, disponible en .NET Framework 4.6.2 y superior a través del paquete Microsoft.Bcl.Memory, y ese es el único paquete que este artículo te pide instalar alguna vez. Para arrancar un proyecto de garabato, el SDK de .NET trae Visual Basic en la caja:

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

Tu primera codificación: bytes dentro, texto fuera

El noventa por ciento de la vida de codificación en Visual Basic son dos llamadas, y el orden importa: el codificador toma bytes, no texto, así que si empiezas con una cadena primero eliges una codificación para convertirla en bytes, y solo entonces haces el paso Base64. Aquí tienes todo el baile:

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

Ese tramo central de tres líneas es todo el oficio, y la cadena "TWFu" es la prueba de humo perfecta para cualquier codificador que escribas. Las sobrecargas te dan control cuando lo necesitas. Las formas de subconjunto codifican una porción de un array sin copiarla fuera primero, lo que viene bien cuando el paquete real está dentro de un buffer más grande:

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==  (solo se codificaron los bytes 3 a 6)
    End Sub
End Module

Y la forma de array a caracteres, ToBase64CharArray, escribe en un buffer de caracteres que tú asignas y te dice cuántos caracteres llenó, que es la herramienta correcta cuando el destino es parte de una estructura de texto más grande que estás construyendo a mano. Anota la regla de casa para la sintaxis de Visual Basic: un array de bytes se escribe Byte() con los paréntesis vacíos. Si los quitas, tienes un byte suelto, y Option Strict On (desactivado por defecto en las plantillas - vale la pena activarlo en cada proyecto) caza el descuido en tiempo de compilación.

Dando forma a la salida: padding, saltos de línea y tamaños exactos

Codificar los mismos bytes dos veces puede producir legítimamente dos cadenas distintas, y las diferencias se reducen todas a dar forma a la salida. Primero, el padding: cuando la longitud de entrada no es múltiplo de tres, el codificador rellena el grupo final con uno o dos caracteres =. El RFC dice incluirlos a menos que la especificación que sigas diga lo contrario, y ToBase64String los incluye por defecto. Segundo, los saltos de línea: el segundo parámetro de las sobrecargas de formato, Base64FormattingOptions.InsertLineBreaks, hace que el codificador emita líneas de 76 caracteres separadas por CRLF, que es exactamente la regla MIME. El MIME en sí usa un límite de 76 caracteres, un pariente cercano de las antiguas líneas de 64 caracteres de PEM, y ambos límites remontan a restricciones dentro de SMTP. Si tu consumidor es un pipeline de email, activa los saltos de línea; si es una URL, un campo JSON o una columna de base de datos, déjalos desactivados, porque un CRLF invisible dentro de tus datos encontrará la manera de sorprenderte más tarde:

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: dos líneas de 76 caracteres más un CRLF entre ambas
    End Sub
End Module

Tercero, los tamaños exactos, porque querrás preasignar buffers y anchos de columna. La regla es cuatro caracteres por cada tres bytes de entrada, redondeando hacia arriba: 1000 bytes se convierten en 1336 caracteres. En vez de hacer la aritmética a mano, el runtime tiene un helper que devuelve la longitud máxima codificada para un tamaño de entrada dado, que es lo que pasas a la asignación del buffer:

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

Esa misma proporción de cuatro por tres es el impuesto de tamaño en su forma más pura: cada valor codificado es aproximadamente un 33 por ciento más grande que los bytes que lleva, así que planifica tus tamaños de almacenamiento y transferencia con ese margen en mente. Y un comportamiento que vale la pena conocer antes de que te muerda: si decodificas una cadena y luego recodificas el resultado, la cadena nueva no está garantizada para coincidir con la original, porque los espacios en blanco desaparecen y el padding se normaliza. Compara bytes decodificados cuando necesites comparar valores, no el texto codificado.

Elegir el charset antes de codificar

Como el primer paso de la codificación de texto es "de cadena a bytes", el charset que elijas decide lo que el receptor ve al decodificar. Las cadenas de Visual Basic son UTF-16 dentro del runtime, pero los bytes que emites deberían coincidir con lo que el otro lado espera leer, y el menú de opciones es corto:

  • Encoding.UTF8: el valor por defecto correcto para la web, las APIs y cualquier cosa moderna. Hace ida y vuelta con cada carácter Unicode que el lenguaje puede albergar.
  • Encoding.Unicode: UTF-16 little-endian. Una elección razonable cuando ambos extremos de la tubería son programas .NET que acordaron explícitamente UTF-16, y nada más.
  • Encoding.ASCII: solo de 7 bits, y sustituirá en silencio cualquier otra cosa por un signo de interrogación. Codificar "Café" como ASCII te da los bytes de "Caf?", que se decodificará de vuelta a exactamente eso, signo de interrogación incluido.
  • Encoding.Default: en .NET Framework era la página de códigos ANSI de la máquina, pero en .NET (Core) es siempre UTF-8 sin importar la localización. Evítalo igualmente para datos que intercambias - nombra la codificación explícitamente, normalmente 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==  (el acento se convirtió en signo de interrogación)
    End Sub
End Module

Dos cadenas Base64 distintas, una palabra, y solo una de ellas sobrevive el viaje. La regla práctica: a menos que el protocolo que sigas nombre otro esquema, codifica el texto como UTF-8 y dilo.

Base64Url: el alfabeto que sobrevive a las URLs

El alfabeto estándar contiene + y /, y ambos caracteres tienen trabajos propios dentro de las URLs, así que el Base64 construido sobre ese alfabeto se rompe en el momento en que cae en una query string o en un segmento de ruta. La solución, estandarizada en la sección 5 del RFC 4648, intercambia a los dos culpables por - y _, que son seguros para URLs, y normalmente descarta el padding final porque la longitud de los datos ya le dice al decodificador dónde acaban. Esta variante, conocida como base64url, es el alfabeto de los JWTs, los tokens de API y un número creciente de APIs. .NET 9 añadió una clase dedicada para ella, y viene construida con una opinión que vale la pena conocer: omite el padding por diseño:

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  (guion bajo, sin padding al final)
    End Sub
End Module

El ejemplo de arriba es un buen ejemplo: los bytes elegidos hacen que aparezca uno de los caracteres especiales - el guion bajo, donde el alfabeto estándar tiene una barra - así que puedes ver el intercambio en acción. Cuando estás en un runtime más antiguo, el mismo alfabeto son dos sustituciones de caracteres más un recorte, y obtienes un resultado compatible de sustitución directa:

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

En .NET Framework 4.6.2 o superior, el paquete Microsoft.Bcl.Memory te da en su lugar la clase Base64Url de verdad. En cualquier caso, fíjate en la línea de arena del padding: la salida de Base64Url de .NET no tiene padding, mientras que algunas librerías de otros ecosistemas lo añaden (y unos cuantos decodificadores estrictos insisten en él). El JWT, por ejemplo, exige la forma sin padding, así que el valor por defecto de .NET es exactamente correcto ahí. Cuando cruces una frontera de ecosistema, comprueba la expectativa del otro lado antes de enviar la cadena.

Empaquetando archivos

Los archivos son el caso de uso original: convertir un archivo binario en un archivo de texto que el email, el FTP y los sistemas de configuración cargarán gustosos. En Visual Basic el trabajo completo son tres llamadas, una de las cuales lee y otra escribe:

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

Guarda la proporción de tamaño en el bolsillo: una foto de 10 megabytes se convierte en un archivo de texto de unos 13,4 megabytes. La operación es rápida en hardware moderno (más abajo se habla de ello), así que el coste casi siempre es almacenamiento y ancho de banda en vez de CPU, que es la factura habitual del impuesto del 33 por ciento. Cuando el archivo solo va a vivir junto al texto que lo referencia, este patrón está perfectamente bien; cuando el archivo es grande y de vida larga, pregúntate si el canal necesita siquiera la forma de texto.

Imágenes: construyendo data URIs a mano

El esquema data URI (RFC 2397) incrusta el contenido de un archivo directamente en una URL: data:, el tipo de medio, el marcador literal ;base64, una coma y los bytes codificados. Los navegadores los usan para incrustar imágenes pequeñas y fuentes. WPF no puede consumir un data URI directamente - BitmapImage no tiene manejador para el esquema data: - así que el movimiento idiomático es quitar el prefijo y pasar los bytes a un MemoryStream. Construir la URI en Visual Basic es una concatenación de cadenas, y consumirla es un pequeño bloque de init:

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()
        ' ahora image se puede asignar a un control Image
    End Sub
End Module

El propio RFC avisa de que los data URIs solo son útiles para valores cortos, y los documentos HTML imponen sus propios límites de longitud de atributo, así que el alcance sensato es iconos, avatares, miniaturas y patrones de fondo diminutos. El tipo de medio tiene que coincidir con los bytes que realmente codificaste, porque nada aguas abajo lo volverá a derivar del contenido.

HTTP: cabeceras de auth y payloads JSON

En el cable, los dos sitios donde codificarás a mano son la cabecera HTTP de Basic auth y los campos JSON que llevan datos binarios o precodificados. La Basic auth es la más visible: la cabecera es la palabra Basic, un espacio y el Base64 de username:password unido con un signo de dos puntos. Construirlo es una llamada de codificación:

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

El caso JSON es igual de rutinario. Si una API quiere una imagen o un certificado dentro del cuerpo de una petición, codificas los bytes y sueltas la cadena en el payload, y System.Text.Json (en la caja desde .NET Core 3.0) se encarga de la serialización alrededor:

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

Dos reglas de casa: envía credenciales solo sobre HTTPS, porque sobre HTTP plano el Base64 es un disfraz, no un candado, y nunca registres la cabecera de auth cruda ni las credenciales a las que decodifica.

Adjuntos de email y envoltorio MIME

El email es donde el Base64 ganó su sustento. SMTP se construyó para ASCII de 7 bits, así que un adjunto binario tiene que convertirse en texto antes de poder volar, y el estándar MIME (RFC 2045) hizo la elección: Base64, envuelto a 76 caracteres por línea, declarado con una cabecera Content-Transfer-Encoding: base64. Si trabajas con las clases System.Net.Mail, el ritual completo son dos líneas de configuración, porque la librería de correo hace el envoltorio por ti en el momento de enviar:

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

Solo necesitas producir tú mismo la forma envuelta, con Base64FormattingOptions.InsertLineBreaks, cuando escribes texto MIME crudo a mano: un fixture de pruebas de correo, una pasarela legada o una herramienta que escupe archivos .eml. La regla de 76 caracteres no es una preferencia de estilo; algunos sistemas receptores truncan las líneas más largas, que es la razón por la que el límite ha sobrevivido en el estándar durante décadas.

Guardando valores codificados: bases de datos, archivos de configuración y variables de entorno

El almacenamiento solo de texto no deja de pedir Base64: una columna de base de datos de tipo texto, un valor de configuración en XML, una variable de entorno. Codificas los bytes, guardas la cadena y la decodificas en la salida. El lado de codificación es siempre la misma línea mágica, pero el lado de almacenamiento tiene límites que hacen el impuesto de tamaño concreto. Una columna VARCHAR normal en SQL Server se detiene en 8.000 caracteres (una columna NVARCHAR se detiene en la mitad, 4.000 caracteres, porque cada carácter Unicode cuesta dos bytes) - 8.000 caracteres es sitio para unos 6.000 bytes de binario antes de que el sobrecoste del 33 por ciento te empuje por encima, más allá de lo cual recurres a los tipos MAX o, con más honestidad, a una columna binaria de verdad. En Windows, una variable de entorno definida por el usuario está limitada a 32.767 caracteres (y en sistemas de la época de XP el bloque de entorno entero también estaba limitado a ese tamaño), así que "guardar el blob entero de la licencia en una variable de entorno" tiene un techo duro:

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

Los archivos de configuración siguen la misma forma, con el valor viviendo en texto XML o JSON y la decodificación pasando en tu código de arranque. Una nota legada para la esquina empresarial: WCF y los contratos de datos XML serializan un array de bytes como el tipo de esquema XML base64Binary, así que un gran cuerpo de servicios .NET antiguos guarda binarios exactamente de esta forma, y el valor que encuentres en ese XML es salida plana de ToBase64String.

JWTs: construyendo la forma compacta

Un JSON Web Token en forma compacta son tres piezas de base64url separadas por puntos: la cabecera, el payload y una firma. Las dos primeras son JSON plano, y la tercera es una prueba criptográfica de que un portador de la clave correcta construyó este token. Construir la forma sin firmar a mano son dos codificaciones y una unión de cadenas, pero un JWT real necesita el paso de la firma, y un pequeño ejemplo de HMAC-SHA256 hace todo el conjunto concreto:

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

Ejecútalo con la cabecera {"alg":"HS256","typ":"JWT"} y un payload a tu elección, y el resultado es un JWT compacto de verdad: sin padding en ninguna parte, caracteres URL-safe en las tres partes. Fíjate en que la firma también es base64url, porque el token entero tiene que sobrevivir a una URL o a una cabecera HTTP. Para sistemas de producción, el paquete System.IdentityModel.Tokens.Jwt (el conjunto IdentityModel del equipo Microsoft Entra) construye, firma y verifica estos tokens por ti, que es la capa donde pertenecen la gestión de claves, el anclaje de algoritmos y las comprobaciones de caducidad. Rodar la codificación a mano está bien para entender y para herramientas pequeñas; para lo que custodia el acceso, deja que la librería cargue el peso.

Trampas: dónde resbalan los codificadores VB

Las trampas de aquí son una mezcla de hábitos de lenguaje y sorpresas de forma de salida, y la mayoría cuestan una sesión de depuración en vez de un choque:

  • Byte frente a Byte(). El codificador quiere un array. En Visual Basic un byte suelto es Byte y un array es Byte(), y la diferencia es un par de paréntesis. Bajo Option Strict On un fallo es un error de compilación; con él desactivado, puedes en su lugar llevarte una sorpresa en tiempo de ejecución. Mantén el rigor activado y los paréntesis a la vista.
  • La trampa de Encoding.Default, al revés. La historia de la divergencia por localización es de .NET Framework: en .NET moderno, Default es siempre UTF-8, así que la misma cadena se codifica igual en cada máquina. Para cualquier cosa que cruza máquinas, nombra la codificación explícitamente, normalmente UTF-8 - el consejo vale en cualquier caso.
  • El CRLF tiene modo de entrar. InsertLineBreaks es maravilloso para MIME y terrible para URLs, JSON y columnas de texto de base de datos, donde inserta un retorno de carro y un salto de línea que nadie pidió. Úsalo solo cuando el consumidor espera líneas envueltas, y si dudas, usa el valor por defecto None.
  • Descalces de padding en la frontera. El Base64Url de .NET no emite padding, mientras que algunas librerías de otros ecosistemas lo añaden (y unos cuantos decodificadores estrictos lo exigen). Cuando tu valor codificado cruza un ecosistema, confirma la expectativa del otro lado antes de enviar la cadena; el JWT quiere la forma sin padding, que es el valor por defecto de .NET.
  • Los recorridos de ida y vuelta no son identidad. Decodifica una cadena envuelta y con padding y recodifícala, y obtienes una línea limpia y única con padding nuevo, no el texto original. Si tu lógica compara valores codificados por igualdad, compara los bytes decodificados en su lugar.
  • El techo de tamaño es real. La fórmula de longitud de salida, cuatro caracteres por cada tres bytes redondeando hacia arriba, desborda un recuento de 32 bits con aproximadamente 1,5 gigabytes de entrada, y el codificador responde con una OutOfMemoryException en vez de una cadena parcial. Para entradas en cualquier sitio cerca de esa escala, usa streaming en su lugar (abajo).
  • El muro de los spans. Los codificadores basados en spans se pueden llamar desde VB en el punto de llamada: pasa tus arrays Byte() o Char() directamente y el compilador los convierte. Pero no puedes declarar una variable, un campo o un parámetro de tipo Span o ReadOnlySpan; el compilador se niega con "Types with embedded references are not supported in this version of your compiler". El idiom de VB es llamar a las APIs de span con arrays planos y no guardar nunca un span.
  • BitConverter no es Base64. BitConverter.ToString(bytes) renderiza hexadecimal con guiones entre los pares, así que es una respuesta equivocada tentadora que produce 4D-61-6E donde el otro sistema espera TWFu. Para Base64, la clase es System.Convert, cada vez.

Velocidad y tamaño: notas de rendimiento

La reputación de Base64 como "codec de texto lento" no sobrevive al contacto con el runtime moderno. El codificador dentro de .NET corre código vectorizado por hardware cuando la máquina lo soporta, con rutas rápidas dedicadas para los conjuntos de instrucciones AVX-512, AVX2 y SSE, y la ruta AVX-512 mastica 48 bytes por paso. Para paquetes ordinarios, la llamada clásica de ToBase64String es lo bastante rápida como para que el algoritmo rara vez sea el cuello de botella; los costes que sientes son el impuesto de tamaño del 33 por ciento y, para las rutas calientes, las asignaciones intermedias. Si codificas millones de valores pequeños, las APIs basadas en spans son el refinamiento: TryToBase64Chars escribe en un span de caracteres que controlas e informa del éxito con un booleano, y System.Buffers.Text.Base64 va más lejos, codificando directamente en buffers UTF-8 que tú asignas e incluso inflando datos 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

El patrón a fijar es que dimensionas el buffer con el helper, codificas en él y solo conviertes a cadena el prefijo usado, lo que mantiene la superficie intermedia tan pequeña como pueda. Y para archivos lo bastante grandes como para incomodar a las cadenas, el par de streaming mantiene la memoria plana: la transformación ToBase64Transform envuelta en un CryptoStream lee tu entrada en trozos y escribe texto codificado, así que un archivo de dos gigabytes nunca tiene que convertirse en una cadena de 2,7 gigabytes de una pieza:

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

Una nota al futuro: las librerías en vista previa de .NET 11 añaden nuevas sobrecargas cómodas y de span a los tipos Base64 existentes, así que si tu proyecto puede seguir vistas previas, la caja de herramientas sigue creciendo; si no, todo lo de arriba es estable en cada release soportada.

Una breve historia: de MSXML a los spans

Mucho antes de .NET, los programas de Visual Basic que necesitaban Base64 lo pedían prestado al mundo COM. El truco clásico de VB6 y VBA (el lenguaje de macros que sigue corriendo dentro de Excel y Office) usaba en su lugar un elemento XML DOM: el parser de MSXML deja que un nodo declare su DataType como bin.base64, así que escribir tus bytes en el nodeTypedValue del nodo y leer de vuelta su propiedad text te entrega la cadena codificada, con el DOM haciendo la matemática Base64 de verdad (la propiedad Charset del propio objeto Stream de ADO solo entiende nombres de charset reales como "utf-8" o "iso-8859-1", no "base64", así que no juega ningún papel en la conversión en sí). Era ingenioso, estaba en todas partes, y es la razón por la que "base64 VBA" sigue encendiendo motores de búsqueda décadas después. La era terminó en 2002, cuando la primera versión .NET del lenguaje, Visual Basic 7.0, se unió al nuevo Common Language Runtime, y el .NET Framework trajo System.Convert con ToBase64String en la caja. Desde .NET Framework 1.1 en 2003, cada programa VB podía codificar Base64 con una llamada y sin componentes que registrar.

Los capítulos modernos son cortos. En 2018, .NET Core 2.1 añadió el método TryToBase64Chars con poca asignación y la clase de bajo nivel basada en spans System.Buffers.Text.Base64. En 2024, .NET 9 estandarizó el alfabeto URL-safe como Base64Url, acabando con una década de llamadas a Replace hechas a mano. A fecha de 2026, .NET 10 - lanzado en noviembre de 2025 - es la release de soporte a largo plazo que lo lleva todo, y las librerías en vista previa de .NET 11 están añadiendo una nueva generación de métodos cómodos, así que el codificador, desde la línea de 2003 hasta la era de los spans, es la historia de la misma clase volviéndose más rápida y más precisa, nunca de empezar de cero.

Datos curiosos, edición VB

  • InsertLineBreaks reproduce la regla MIME de 76 caracteres exactamente, CRLF incluido, lo que significa que los saltos de línea que tu codificador escribe en 2026 tienen la misma forma byte a byte que los que un estándar de email definió en los años 90.
  • El operador IsNot, añadido con Visual Basic 2005, llegó a salir en las noticias como objeto de una solicitud de patente de Microsoft. Muy pocos operadores de lenguaje pueden reclamar esa distinción.
  • El primer Visual Basic salió en 1991, antes de que existiera la World Wide Web. Para cuando el esquema data URI apareció en 1998, el Base64 ya llevaba cinco años cargando adjuntos de email, y el VB se había hecho mayor como lenguaje de 32 bits tres años antes, con Visual Basic 4 en 1995.
  • En hardware con AVX-512, el codificador del runtime procesa 48 bytes por paso vectorial, que es la diferencia entre una consulta de tabla en un museo y una cinta transportadora en una fábrica.
  • El espacio de nombres My, la famosa capa de azúcar de Visual Basic desde 2005, nunca necesitó añadir un helper de Base64. System.Convert estuvo siempre a un import de espacio de nombres, un caso raro donde el runtime de VB no añadió nada a una historia que el framework ya contaba.

El otro lado

Este artículo ha cubierto el lado de codificación del Base64 en Visual Basic: la caja de herramientas, las decisiones de forma de salida, el alfabeto URL-safe y los casos de uso desde archivos hasta JWTs. La dirección contraria, tomar una cadena entrante y convertirla de vuelta en los bytes que esconde, tiene su propio conjunto de comportamientos, reglas de perdón y trampas, y está cubierta en todo detalle en el artículo de decodificación compañero del sitio hermano. El enlace a ella está justo debajo de esta línea, y la herramienta de la página de inicio sigue siendo la forma más rápida de codificar un paquete pequeño a mano.

Última actualización: 2026-09-08

Artículo relacionado: Decodificación Base64 en Visual Basic: una guía completa