Приходится иметь дело с форматом Base64? Тогда этот сайт идеально вам подойдет! Воспользуйтесь нашим невероятно удобным онлайн-инструментом для кодирования или декодирования ваших данных.

Декодирование Base64 в Visual Basic: полное руководство

Представьте картину: в ваш проект на Visual Basic приземляется строка. Она похожа на перетасованную колоду из букв и цифр, где изредка попадаются знак плюс, слеш или знак равно, а человек, который её прислал, клянётся, что раньше это была совершенно обычная фраза, JPEG или конфигурационный блок. Эта строка - Base64, и эта страница - ваше полевое руководство по превращению её обратно в то, чем она была. Хорошая новость сразу: у Visual Basic есть полноценный декодер Base64 с самых ранних времён .NET Framework, он живёт прямо в среде выполнения, и чтобы им пользоваться, не нужно устанавливать ни единого пакета.

Короткое повторение, потому что домашняя страница этого сайта объясняет формат во всех деталях: Base64 записывает три байта четырьмя символами, взятыми из 64-символьного алфавита, и один или два завершающих = помечают место, где закончились настоящие данные. Поэтому закодированный текст немного пухлее оригинала: четыре символа на каждые три входных байта, примерно на треть больше. Декодирование просто проворачивает эту сделку в обратную сторону. Раз картина проблемы ясна, откроем-ка наши конверты.

Семейство декодеров: одна среда выполнения, четыре эпохи

Всё, что нужно для декодирования, живёт в среде выполнения .NET. За последние два десятилетия она росла четырьмя волнами, и старшие волны работают ровно так же, как всегда, так что на практике вы встретите все четыре:

API Доступен с Для чего
System.Convert.FromBase64String .NET Framework 1.1 (2003) Классика. На входе одна строка, на выходе свежий массив Byte(). Бросает исключение на неверном входе.
System.Convert.FromBase64CharArray .NET Framework 1.1 (2003) То же самое декодирование, но чтение идёт из среза символьного массива, которым вы уже владеете.
System.Convert.TryFromBase64String, TryFromBase64Chars .NET Core 2.1 (2018) Булево значение вместо исключений, запись в буфер, который вы предоставляете. Дружелюбный страж для недоверенного ввода.
System.Buffers.Text.Base64 .NET Core 2.1 (2018) Низкоуровневое декодирование на спанах: коды состояния вместо исключений, декодирование на месте и предварительные проверки через IsValid.
System.Buffers.Text.Base64Url .NET 9 (2024) URL-безопасный алфавит (- и _ вместо + и /), с необязательным заполнением. На старых средах выполнения едет в пакете NuGet Microsoft.Bcl.Memory.
FromBase64Transform + CryptoStream .NET Framework 1.1 (2003) Потоковое декодирование: файл в файл, сеть на диск, кусок за куском, без удержания всей нагрузки в памяти.

Одно уточнение по Visual Basic, прежде чем идти дальше. В VB-проекте голое имя Convert разрешается в System.Convert, потому что стандартные шаблоны проектов импортируют пространство имён System за вас, и ничего в среде выполнения Visual Basic не заслоняет это имя. Тем не менее эта статья в основном пишет полную форму System.Convert: это ничего не стоит, и намерение становится безапелляционно ясным любому, кто читает код.

Про версии: .NET 10 - текущий выпуск с долгосрочной поддержкой (ноябрь 2025, поддерживается до ноября 2028), .NET 8 и .NET 9 оба поддерживаются до ноября 2026, а .NET 11 находится в превью и добавляет пачку новых удобных методов Base64. API декодирования стабильны во всех этих версиях. Единственный порог версии - Base64Url: он встроен начиная с .NET 9, а на .NET Framework 4.6.2 или новее его можно подтянуть пакетом Microsoft.Bcl.Memory. Больше ничего в этой статье не требует пакетов.

Если вы начинаете с нуля, .NET SDK включает Visual Basic из коробки, так что вот весь ритуал:

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

В итоге у вас появится небольшой Program.vb с Imports System вверху, и вы готовы декодировать.

Однострочник: FromBase64String

Девяносто процентов жизни декодирования в Visual Basic - это один вызов. Передайте ему строку, и он вернёт точные байты, которые были в ней упакованы:

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

Три вещи стоит запомнить. Первая: результат - это байты, а не текст: декодер байтовый от и до, и именно этого вы хотите, потому что нагрузка может быть фразой, JPEG, сертификатом или хэшем, и ни один из них не следует считать особым. Превращение этих байтов в читаемую строку - отдельный, осознанный шаг через объект Encoding, и именно в этом шаге живёт ваше решение о кодировке (об этом ниже). Вторая: FromBase64String выделяет свежий массив ровно под длину декодированных данных, так что вам никогда не приходится таскать за собой запас по размеру. Третья: "TWFu" декодируется в слово «Man», три байта, никаких сюрпризов, что делает его идеальным дымовым тестом для любого кода декодирования, который вы пишете.

Что декодер прощает, а что отвергает

Вот где у декодера .NET начинается характер, и характер выразительный: он щедр ровно в одной вещи и безжалостен ко всему остальному. Щедрость - к пробельным символам. Декодер пропускает ровно четыре символа, где бы они ни встречались: пробел (U+0020), табуляция (U+0009), перевод строки (U+000A) и возврат каретки (U+000D). Эта политика - осознанное уважение к электронной почте, где нагрузки Base64 приходят, обёрнутые в короткие строки, и это значит, что обёрнутое по MIME вложение декодируется без какой-либо предобработки. Весёлый факт: эту терпимость разделяет всё встроенное семейство, включая класс на спанах System.Buffers.Text.Base64 и URL-безопасный класс Base64Url, так что вы получаете одно и то же снисходительное поведение, какой бы API ни выбрали. Всё, что вне 64-символьного алфавита, любое нарушение правил длины и любое заполнение не на месте получают исключение. Вот тот же декодер встречает несколько разных входов:

Вход Результат
"TWFu" Декодируется в Man (3 байта).
"TWF" + CRLF + "u" Декодируется в Man. Переносы строк посередине невидимы для декодера.
"TWFu" + неразрывный пробел FormatException. Пропускаются только четыре пробельных символа из перечисленных выше; неразрывный пробел к ним не относится.
"TWE" FormatException. Если не считать пробельных символов, длина должна быть кратна 4.
"TWFu=" FormatException. Заполнение после того, как данные закончились, не допускается.
"====" FormatException. Больше двух символов заполнения - невалидно.
"" или только пробельные символы Пустой массив байтов. Тихий, валидный успех.
"TW=u" FormatException. Заполнение посередине невалидно.

Так что честный договор маленький и запоминающийся: ссылка Nothing бросает ArgumentNullException, пустой вход или вход только из пробельных символов декодируется в пустой массив, валидный вход декодируется в байты, а всё остальное невалидное бросает одно очень конкретное исключение - FormatException.

От байтов к тексту: выбор кодировки

В момент, когда вы решаете, что декодированные байты - это на самом деле текст, вам приходится назвать кодировку, потому что байты не становятся текстом, пока вы не скажете, как их читать. Строки Visual Basic внутри - это UTF-16, но байты, выходящие из декодера, были сделаны кем-то другим, вероятно, по другой схеме, так что вам нужно совпасть с их выбором. Практическое меню:

  • Encoding.UTF8: безопасная настройка по умолчанию для всего, что путешествовало по вебу или через API. Если сомневаетесь - начинайте отсюда.
  • Encoding.Unicode: UTF-16 little-endian, нативный сорт .NET. Разумно, когда обе стороны обмена - программы .NET, которые явно выбрали UTF-16.
  • Encoding.ASCII: только 7 бит. Байты вне ASCII заменяются вопросительным знаком, так что это выбор с потерями, который молча уничтожает акценты.
  • Encoding.Default: на .NET Framework это была ANSI-кодировка машины, но на .NET (Core) это всегда UTF-8, независимо от локали. Всё равно избегайте его для данных, которыми обмениваетесь - называйте кодировку явно, обычно Encoding.UTF8.
Imports System
Imports System.Text
Module CharsetDemo
    Sub Main()
        ' Слово "Café", сохранённое в байтах 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

Прочтите те же пять байтов через Encoding.Unicode - и получите короткую строку чуши: парочка странных символов из CJK-диапазона плюс символ замены, потому что декодер складывает байты в пары по два. Прочтите байты UTF-8 слова «Café» через Encoding.ASCII - и акцент станет ??, парой вопросительных знаков, потому что акцент в UTF-8 - это два байта. Ни один из этих выборов не бросает исключение; они просто молча производят неверный текст. Именно поэтому кодировка - решение, которое вы принимаете осознанно, а не значение по умолчанию, которое вы наследуете.

URL-безопасный алфавит: Base64Url

Стандартный Base64 использует + и /, и оба этих символа несут собственный смысл внутри URL, так что стандартный алфавит может сломать ссылку в ту самую секунду, когда попадает в строку запроса. Исправление, стандартизированное в RFC 4648, раздел 5, - это URL- и файловый вариант: та же схема из 64 символов, где - занимает место +, а _ место /, причём завершающее заполнение обычно отбрасывается, потому что оно и так следует из длины. Вы встретите этот алфавит в JWT, API-токенах и везде, где Base64 едет внутри URL. В .NET 9 для него появился специальный класс - System.Buffers.Text.Base64Url, и пользоваться им одно удовольствие:

Imports System.Buffers.Text
Imports System.Text
Module UrlSafeOpener
    Sub Main()
        ' URL-safe вход, без заполнения в конце
        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

Два поведения стоит знать. Кодировщик Base64Url по замыслу производит вывод без заполнения, но его декодер принимает и заполненные, и незаполненные данные, так что он дружелюбен к данным из других экосистем. А Base64Url.IsValid позволяет предварительно проверить строку-кандидата до декодирования, что удобно, когда данные приходят из внешнего мира. Если вы застряли на старой среде выполнения без этого класса, преобразование - это две замены символов и дозаправка заполнением, точный обратный ход тому, что делал кодировщик:

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

На .NET Framework 4.6.2 или новее можно вместо этого установить пакет NuGet Microsoft.Bcl.Memory и использовать настоящий класс Base64Url. В любом случае правило простое: распознавайте алфавит по контексту (URL, JWT, API-токен), а потом выбирайте подходящий декодер.

Открываем файлы

Одно из старейших применений Base64 - контрабанда двоичных данных через текстовые файлы: файл .b64 или .txt, в котором лежат закодированные байты. В Visual Basic путь туда и обратно - два файловых вызова и одно декодирование. Прочитайте текст, декодируйте его, запишите байты:

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

Снисходительность к пробельным символам делает это надёжным в самом приятном смысле: файлу всё равно, была ли нагрузка записана одной длинной строкой, обёрнута по 76 символов или по 64, потому что декодер пропускает переносы строк в любом случае. Держите в кармане один факт о размере: текстовый файл примерно на треть больше, чем двоичный, который он прячет, так что файл в 10 мегабайт прибудет примерно 13,3 мегабайтами символов. Ничего драматичного, но это то число, которое стоит помнить, когда «маленький» текстовый файл кажется большим.

Изображения и data URI

Схема data URI (RFC 2397) позволяет URL нести собственный контент: data:, за ней тип медиа, литеральный маркер ;base64, запятая, а затем закодированные байты. Вы видели её повсюду в вебе, в HTML и CSS, где она встраивает маленькие изображения и шрифты прямо в разметку, вместо того чтобы указывать на отдельный файл. В Visual Basic разбор одного такого URI - это просто разрез строки и декодирование. Пример ниже вытаскивает PNG из data URI и собирает из него изображение 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

Обратите внимание на защитную проверку заголовка: data URI без маркера ;base64 содержит вместо этого процентно-закодированные данные, и декодирование их как Base64 либо завершится ошибкой, либо даст мусор. Сам RFC предупреждает, что data URI полезны только для коротких значений, а у HTML есть собственные ограничения на длину атрибутов, так что трактуйте это как правильный инструмент для иконок, аватарок и миниатюр, а не для отправки всей вашей фотобиблиотеки в одном атрибуте.

HTTP, API и Basic auth

Base64 повсюду в веб-API, и два самых распространённых его облика - заголовок Basic auth HTTP и поля JSON, которые несут двоичные или заранее закодированные данные. Basic auth - самый простой случай: клиент присылает Authorization: Basic, за которым следует Base64-код username:password. Декодирование его в Visual Basic - это проверка префикса и один вызов:

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

Функция отдаёт username:password одной строкой, которую вы затем разрезаете по двоеточию. Другой повседневный случай - ответ JSON, где какое-то поле содержит заранее закодированный блок, например изображение или сертификат. С HttpClient и System.Text.Json (System.Text.Json в комплекте начиная с .NET Core 3.0, а HttpClient и вовсе давно) паттерн прямолинеен:

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

Две служебные заметки. Никогда не выводите декодированные учётные данные в лог или интерфейс только потому, что можете, и никогда не полагайтесь на Basic auth поверх обычного HTTP, потому что тогда вы просто записали пароль более интересным алфавитом.

JWT: читаем три куска

JSON Web Token в компактной форме - это три части Base64Url, разделённые точками: заголовок, пелод и подпись. Первые два - обычный JSON, который можно прочитать глазами (или одним вызовом декодирования), а третья - криптографическая подпись, которую нужно проверять правильным ключом, а не декодировать. Образец токена из распространённой демонстрации выглядит так: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.W-5gI_FdnMBdpgG4twX96rptvh13gmXQ75kKLRXVaGs. Чтобы прочитать его пелод в Visual Basic, нужно разрезать по точкам, перевести URL-безопасный алфавит обратно в стандартный и декодировать:

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
        ' Возвращаем URL-safe алфавит обратно к стандартному
        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

Запустите это против образца токена - и получите JSON {"sub":"1234567890","name":"John Doe"}. Прочтите заголовок тем же способом - и получите {"alg":"HS256","typ":"JWT"}. Предупреждение, которое здесь важно: читать JWT - не значит проверять JWT. Любой может изготовить токен, так что прежде чем доверять любому утверждению внутри него, проверьте подпись ключом издателя. Для этой задачи пакет NuGet System.IdentityModel.Tokens.Jwt (набор IdentityModel от команды Microsoft Entra) берёт на себя детали Base64Url, проверку подписи и разбор утверждений - ровно тот слой, где вы не хотите крутить собственное колесо.

Вложения в почте, обёрнутые по 76 символов

Электронная почта - место, где Base64 заработал свою репутацию. SMTP проектировался для 7-битного ASCII, поэтому двоичное вложение должно стать текстом, прежде чем оно сможет полететь, и стандарт MIME (RFC 2045) выбрал Base64 с лимитом строки в 76 символов - близкого родственника ещё более старых 64-символьных строк PEM. Если вы когда-нибудь получали сырое письмо, вы видели результат: плотный блок Base64, разбитый на аккуратные короткие строки, под заголовком Content-Transfer-Encoding: base64. Красивая часть для декодера в том, что вам не нужно разворачивать ничего. Декодер .NET пропускает переносы строк и пробелы, где бы они ни встречались, так что обёрнутый блок декодируется как есть:

Imports System
Imports System.Text
Module MimeOpener
    Sub Main()
        ' Фраза из 59 байтов, обёрнутая по MIME по 76 символов с 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

Если вы работаете с классами System.Net.Mail, декодирование ещё менее заметно: вложение Attachment, которое вы добавляете в MailMessage, несёт ContentEncoding со значением TransferEncoding.Base64, и почтовая библиотека обёртывает, отправляет и разворачивает весь ритуал за вас. Вручную декодировать нужно только тогда, когда вы читаете сырой MIME из потока, тестового фикстура или файла устаревшего почтового ящика.

Базы данных, конфигурация и переменные окружения

Хранилища только с текстом снова и снова просят Base64: столбец базы данных, типизированный как текст, значение в XML-конфигурации, переменная окружения. Все они хотят обычные символы, поэтому двоичные данные кодируются перед тем, как попасть в хранилище, и декодируются при возврате. Сторона декодирования - всегда тот же однострочник, а интересная часть - арифметика размеров. Обычный столбец NVARCHAR в SQL Server упирается в 8000 символов, что означает примерно 6000 байтов двоичных данных, прежде чем тридцатипроцентный налог вытолкнет вас за предел; дальше вы тянетесь к вариантам MAX или, честнее говоря, к настоящему двоичному столбцу. В Windows одна пользовательская переменная окружения ограничена 32767 символами (а на системах эпохи XP так же ограничивался и весь блок окружения), поэтому идея «сложить весь лицензионный блок в переменную окружения» имеет твёрдый потолок. Вот паттерн декодирования, который стоит держать в углу головы: сверка сохранённого отпечатка с файлом, со сравнением за фиксированное время, чтобы расхождение не привело к утечке информации через тайминги:

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

Та же форма работает для любого сохранённого хэша: декодируйте сохранённое значение, посчитайте свежий хэш и сравните за фиксированное время. Конфигурационные файлы следуют тому же паттерну, независимо от того, пришло ли значение из записи XML app.config, из JSON-файла настроек или из строки реестра.

Большие данные: декодируем поток, не загружая его

Каждый пример до сих пор читал всю нагрузку в память, что нормально для вложений и значений конфигурации, но неправильно для двух гигабайт файла, которые кто-то закодировал в текстовый файл. Для такого масштаба в .NET есть потоковая пара, существующая ещё с .NET Framework 1.1 (2003): криптографический трансформ FromBase64Transform, обёрнутый в CryptoStream. Вы читаете куски закодированного текста, трансформ декодирует их на лету, а вы записываете байты - так память остаётся плоской, каким бы большим ни был файл:

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

Поскольку закодированный файл - это обычный ASCII-текст, чтение его как потока байтов совершенно безопасно, и трансформ справляется с переносами строк без какого-либо вашего участия. Файл на выходе получается примерно на три четверти размера входного, и это тот же тридцатипроцентный налог, уплаченный при заходе, собирается при выходе.

Подводные камни, кусающие именно Visual Basic

Большинство ловушек этого раздела общее с другими языками .NET, но несколько носят отчётливо VB-шляпу, так что вот они все вместе:

  • Byte против Byte(). В Visual Basic одиночный байт - это Byte, а массив байтов - Byte(), и пустые скобки делают всю работу. Написать Dim b As Byte, когда вы имели в виду Byte(), - классическая ошибка первого дня, и это ровно то, что Option Strict On ловит на этапе компиляции. Если в вашем проекте оно ещё не включено - включите: шаблон dotnet new console -lang VB оставляет решение за вами, а шаблоны проектов Visual Studio выставляют его сами.
  • Стена спанов. Современные API на спанах вызываемы из VB, но только на месте вызова: вы можете передать массив Byte() или Char() прямо в метод, который принимает спан, и компилятор сконвертирует его за вас. Чего вы не можете - так это назвать спан в собственном коде. Объявите переменную, поле или параметр типа Span или ReadOnlySpan - и компилятор ответит «Types with embedded references are not supported in this version of your compiler». Так что идиома VB такова: вызывайте span-API обычными массивами и никогда не пытайтесь хранить спан в переменной.
  • BitConverter - это не Base64. BitConverter.ToString(bytes) рисует байты в шестнадцатеричной записи, разделив их дефисами, что делает его соблазнительно неверным ответом для любого, кто слышал «конвертируй байты в строку». Он охотно выдаст вам 4D-61-6E, когда API ожидает TWFu. Если сомневаетесь - тянитесь к System.Convert.
  • MidB - призрак. Классический Visual Basic имел строковые функции байтового уровня - MidB, LeftB и RightB - нацеленные на двухбайтовые наборы символов. Теперь каждая строка .NET - Unicode, и документация среды выполнения говорит прямо: они больше не поддерживаются. Если устаревший фрагмент кода их использует - перепишите его на массивах байтов и API из этой статьи.
  • Encoding.Default следует за машиной. История о различиях по локали - это история .NET Framework: в современном .NET Default всегда UTF-8, так что одни и те же байты декодируются одинаково везде. Для данных, которыми вы делитесь, называйте кодировку явно, обычно Encoding.UTF8 - совет действует в любом случае.
  • Путешествие туда-обратно - не тождество. Если вы декодируете строку, а затем кодируете результат, новая строка не гарантирована совпасть с исходной: пробельные символы исчезают, а заполнение нормализуется. Нагрузка с переносами строк возвращается одной чистой строкой. Для данных это нормально, но опасно, если ваша логика сравнивает закодированный текст, а не декодированные байты.
  • Вход только из пробельных символов - тихий успех. Строка, состоящая только из пробелов и переносов строк, декодируется в пустой массив байтов без какой-либо ошибки, а это значит, что «пользователь вставил одни переносы» выглядит ровно так же, как «пользователь вставил пустую нагрузку». Если различие важно - проверяйте длину входа до декодирования.

Лучшие практики декодирования

Если выжать из всего вышесказанного одно, то вот привычки, которые держат код декодирования скучным (в лучшем смысле):

  • Относитесь к Base64 как к транспорту, а не к защите. Это кодирование, а не шифрование: любой может прочитать оригинал одним вызовом функции, и RFC 4648 даже отмечает, что небрежное обращение с алфавитом может открыть канал скрытой передачи. Если нужно спрятать содержимое - сначала шифруйте, а затем кодируйте.
  • Для недоверенного ввода предпочитайте методы Try или предпроверку IsValid, а не позволяйте FormatException улететь. Из булева значения проще смастерить дружественное сообщение об ошибке, чем проглатывать исключение.
  • Выбирайте кодировку осознанно и держите UTF-8 значением по умолчанию, пока у вас нет задокументированной причины для другой схемы.
  • Совмещайте алфавит с источником: стандартный Base64 для MIME, почты и конфигурации; Base64Url для JWT и всего, что находится внутри URL.
  • Всё крупное гоняйте потоком через FromBase64Transform и CryptoStream, а не загружайте в строку.
  • Сравнивайте отпечатки и хэши через CryptographicOperations.FixedTimeEquals, а не =, чтобы тайминги не выдавали, какая часть значения совпала.
  • Держите Option Strict On, чтобы семейство оговорок Byte/Byte() было ошибкой компиляции, а не загадкой в проде.

Как Visual Basic получил свой декодер

История начинается в эпоху, когда в Visual Basic не было Base64 вообще. В мире Visual Basic 6 и VBA (языка макросов, который до сих пор работает внутри Excel и Office) разработчикам, которым нужен был Base64, приходилось одолживать его у COM-компонентов, уже стоявших на машине. Знаменитый трюк использовал элемент XML DOM: парсер MSXML позволяет узлу объявить свой DataType как bin.base64, так что если присвоить строке Base64 свойство узла text и прочитать обратно его nodeTypedValue, вы получите сырые байты, причём реальную арифметику Base64 делает DOM (собственное свойство Charset объекта Stream ADO понимает только настоящие имена наборов символов, вроде «utf-8» или «iso-8859-1», но не «base64», поэтому трюк тянется к MSXML). Кодирование прогоняло ту же идею в обратную сторону: байты записывались в nodeTypedValue, а закодированная строка читалась обратно из text:

' Классический трюк декодирования VB6 / VBA, для контекста
Dim node As Object
Set node = CreateObject("MSXML2.DOMDocument").createElement("b64")
node.DataType = "bin.base64"
node.text = packed            ' строка Base64
Dim bytes() As Byte
bytes = node.nodeTypedValue

Он работал, был хитрым, и именно поэтому «base64 VBA» до сих пор подсвечивает поисковики три десятилетия спустя. А потом в 2002 году всё изменилось: Visual Basic 7.0 (первая .NET-версия языка, тогда ещё называвшаяся Visual Basic .NET) влилась в новый Common Language Runtime, и .NET Framework принёс System.Convert с FromBase64String и его друзьями из коробки. С .NET Framework 1.1 в 2003 году каждая VB-программа имела полноценный декодер без единого компонента для регистрации. Современная волна пришла в 2018 году вместе с .NET Core 2.1, который добавил свободные от исключений методы Try и быстрый класс на спанах System.Buffers.Text.Base64, а в 2024 - вместе с .NET 9, который наконец стандартизовал URL-безопасный алфавит как Base64Url. По состоянию на 2026 год .NET 10 - выпущенный в ноябре 2025 - это выпуск с долгосрочной поддержкой, и превью-библиотеки .NET 11 добавляют новое поколение удобных методов Base64, так что декодер продолжает становиться лучше, пока оригинальный однострочник 2003 года идёт своим чередом, неизменным.

Весёлые факты из мира VB

  • Официальный компилятор Visual Basic сам написан на Visual Basic. В рамках открытого проекта Roslyn язык компилирует сам себя.
  • Самый первый Visual Basic вышел в 1991 году, до того как веб-эра разогналась по-настоящему. Большой момент Base64 пришёл с MIME в 1993 году, а сам VB обзавёлся 32-битной способностью два года спустя: Visual Basic 4 в 1995 году впервые сделал возможными 32-битные программы. VB 5 в 1997 году пошёл до конца: только 32 бита, ни грамма 16-битного в коробке.
  • Байтовые функции MidB, LeftB и RightB из классического VB официально «больше не поддерживаются» в .NET, потому что каждая строка VB стала Unicode с самого первого дня .NET Framework. Целое семейство API, выведенное на пенсию выбором кодировки.
  • Base64-механизм среды выполнения - это не старомодное обращение к таблице: современная реализация прогоняет аппаратно-векторизованные пути кода (варианты AVX-512, AVX2 и SSE), когда машина их поддерживает, так что «медленный текстовый кодек» - это не то, что происходит под капотом.
  • Трюк с bin.base64 в MSXML из эпохи VB6 до сих пор крутится в боевых макросах Excel, а значит обходной путь конца 1990-х и вызов Convert из 2003 года благополучно сосуществуют в кодовой базе одной и той же организации.

Прежде чем уходить

Эта статья покрыла сторону декодирования Base64 в Visual Basic: от однострочника до потоков, от JWT до подводных камней с VB-шляпой. Другая сторона монеты - превращение ваших байтов и текста в Base64 в самом начале - имеет собственный набор решений о заполнении, переносах строк и налоге на размер, и она покрыта во всех деталях в сопутствующей статье о кодировании на сестринском сайте. Ссылка на неё находится прямо под этой строкой, а инструмент на домашней странице по-прежнему остаётся самым быстрым способом проверить маленькую нагрузку вручную.

Последнее обновление: 2026-09-08

Связанная статья: Кодирование Base64 в Visual Basic: полное руководство