Як я кодую і декодую рядок base64?


885
  1. Як повернути кодований рядок base64, заданий рядок?

  2. Як розшифрувати кодований рядок base64 в рядок?


4
Якщо це питання та відповідь на "обмін знаннями", я думаю, ми шукаємо щось більш поглиблене. Також з’являється швидкий пошук SO: stackoverflow.com/a/7368168/419
Kev

1
@Gnark Будь-яка рядок кодується певною базовою схемою кодування бітів. Будь то ASCII, UTF7, UTF8, .... Поставлене запитання в кращому випадку є неповним.
Лоренц Ло Зауер

2
Запитайте себе, чи дійсно вам потрібно це робити? Пам'ятайте, що base64 в першу чергу призначений для представлення бінарних даних в ASCII, для зберігання в полі знаку в базі даних або надсилання електронною поштою (куди можна вводити нові рядки). Ви дійсно хочете взяти символьні дані, перетворити їх у байти, а потім перетворити їх назад у символьні дані, на цей раз нечитабельні та без жодних натяків на те, що було оригінальним кодуванням?
bbsimonbb

Чому ми повинні дбати про оригінальне кодування? Ми кодуємо рядок у байти за допомогою представлення UTF8, яке може представляти всі можливі символи рядків. Потім ми серіалізуємо ці дані, а на іншому кінці десеріалізуємо ці дані та реконструюємо ту саму рядок, яку ми мали спочатку (об'єкт string не містить інформації про використовуване кодування). То чому чомусь виникає занепокоєння, пов’язане з використовуваним кодуванням? Ми можемо розглядати це як захищений спосіб представлення серіалізованих даних, який нас ні в якому разі не повинен цікавити.
Младен Б.

Відповіді:


1666

Кодування

public static string Base64Encode(string plainText) {
  var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
  return System.Convert.ToBase64String(plainTextBytes);
}

Розшифруйте

public static string Base64Decode(string base64EncodedData) {
  var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
  return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}

41
Нульові перевірки на вхідні рядки в обох функціях, і рішення ідеально :)
Sverrir Sigmundarson

22
@SverrirSigmundarson: Це чи зробити їх методами розширення.
TJ Crowder

73
@SverrirSigmundarson - навіщо робити нульову перевірку? Він не є тим, хто перенаправляє вхідний рядок. Нульові перевірки повинні запобігати NullReferenceExceptionвашому власному коду, а не чужому.
кен

16
@ken І ще хтось скаже: "Ви повинні викривати лише помилки у власному коді, а не чужий", посилаючись на принцип найменшого здивування, приправлений "невдалою ранністю" та "правильним інкапсуляцією". Іноді це означає помилки обгортання компонентів нижчого рівня, іноді зовсім інше. У цьому випадку я погоджуюся, що усунення помилки deref, безумовно, сумнівне (плюс що ми всі потихеньку погоджуємось з тим, що null як концепція - це трохи хак для початку), але ми все ще можемо побачити деякі ефекти в іншому випадку: ім'я параметра, вказане у винятку, може бути неправильним, якщо його не встановлено.
TNE

6
return System.Text.Encoding.UTF8.GetString (base64EncodedBytes, 0, base64EncodedBytes.Length); для Windows Phone 8
steveen zoleko

46

Я ділюсь своєю реалізацією з деякими акуратними функціями:

  • використовує Методи розширення для класу кодування. Обгрунтування полягає в тому, що комусь може знадобитися підтримувати різні типи кодування (не тільки UTF8).
  • Ще одне поліпшення витончено не вдається з нульовим результатом для введення нуля - це дуже корисно в реальних сценаріях життя і підтримує еквівалентність для X = декодування (кодування (X)).

Зауваження: Пам’ятайте, що для використання методу розширення вам потрібно (!) Імпортувати простір імен за допомогою usingключового слова (у цьому випадку using MyApplication.Helpers.Encoding).

Код:

namespace MyApplication.Helpers.Encoding
{
    public static class EncodingForBase64
    {
        public static string EncodeBase64(this System.Text.Encoding encoding, string text)
        {
            if (text == null)
            {
                return null;
            }

            byte[] textAsBytes = encoding.GetBytes(text);
            return System.Convert.ToBase64String(textAsBytes);
        }

        public static string DecodeBase64(this System.Text.Encoding encoding, string encodedText)
        {
            if (encodedText == null)
            {
                return null;
            }

            byte[] textAsBytes = System.Convert.FromBase64String(encodedText);
            return encoding.GetString(textAsBytes);
        }
    }
}

Приклад використання:

using MyApplication.Helpers.Encoding; // !!!

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Test1();
            Test2();
        }

        static void Test1()
        {
            string textEncoded = System.Text.Encoding.UTF8.EncodeBase64("test1...");
            System.Diagnostics.Debug.Assert(textEncoded == "dGVzdDEuLi4=");

            string textDecoded = System.Text.Encoding.UTF8.DecodeBase64(textEncoded);
            System.Diagnostics.Debug.Assert(textDecoded == "test1...");
        }

        static void Test2()
        {
            string textEncoded = System.Text.Encoding.UTF8.EncodeBase64(null);
            System.Diagnostics.Debug.Assert(textEncoded == null);

            string textDecoded = System.Text.Encoding.UTF8.DecodeBase64(textEncoded);
            System.Diagnostics.Debug.Assert(textDecoded == null);
        }
    }
}

5
Повернення nullу випадку nullє дуже непослідовною поведінкою. Жоден інший API .net, який працює з рядками, не робить цього.
t3chb0t

4
@ t3chb0t сміливо налаштовуйте його під свої потреби. Оскільки спосіб її представлення був налаштований на наш. Це не публічний API;)
andrew.fox

1
Чи не доведеться вам тепер надсилати 2 змінних іншій стороні вашого спілкування (кому ви надсилаєте закодовані дані base64)? Вам потрібно надіслати як використовуване кодування, так і фактичні base64 дані? Чи не простіше, якщо ви використовуєте конвенцію обох сторін, щоб використовувати одне і те ж кодування? Таким чином, вам доведеться лише надсилати базові дані, правда?
Младен Б.

38

Спираючись на відповіді Ендрю Фокса та Себе, я розгорнув їх і зробив для них рядкові розширення замість розширень Base64String.

public static class StringExtensions
{
    public static string ToBase64(this string text)
    {
        return ToBase64(text, Encoding.UTF8);
    }

    public static string ToBase64(this string text, Encoding encoding)
    {
        if (string.IsNullOrEmpty(text))
        {
            return text;
        }

        byte[] textAsBytes = encoding.GetBytes(text);
        return Convert.ToBase64String(textAsBytes);
    }

    public static bool TryParseBase64(this string text, out string decodedText)
    {
        return TryParseBase64(text, Encoding.UTF8, out decodedText);
    }

    public static bool TryParseBase64(this string text, Encoding encoding, out string decodedText)
    {
        if (string.IsNullOrEmpty(text))
        {
            decodedText = text;
            return false;
        }

        try
        {
            byte[] textAsBytes = Convert.FromBase64String(text);
            decodedText = encoding.GetString(textAsBytes);
            return true;
        }
        catch (Exception)
        {
            decodedText = null;
            return false;
        }
    }
}

1
Я додав би ParseBase64 (цей рядовий текст, кодування кодування, рядок decodedText) (щоб заповнити виняток, якщо потрібно, і зателефонував би на TryParseBase64
João Antunes,

22

Незначна зміна відповіді на andrew.fox, оскільки рядок для декодування може бути не правильним кодованим рядком base64:

using System;

namespace Service.Support
{
    public static class Base64
    {
        public static string ToBase64(this System.Text.Encoding encoding, string text)
        {
            if (text == null)
            {
                return null;
            }

            byte[] textAsBytes = encoding.GetBytes(text);
            return Convert.ToBase64String(textAsBytes);
        }

        public static bool TryParseBase64(this System.Text.Encoding encoding, string encodedText, out string decodedText)
        {
            if (encodedText == null)
            {
                decodedText = null;
                return false;
            }

            try
            {
                byte[] textAsBytes = Convert.FromBase64String(encodedText);
                decodedText = encoding.GetString(textAsBytes);
                return true;
            }
            catch (Exception)
            {
                decodedText = null;
                return false;   
            }
        }
    }
}

13

Ви можете використовувати нижче рутини для перетворення рядка у формат base64

public static string ToBase64(string s)
{
    byte[] buffer = System.Text.Encoding.Unicode.GetBytes(s);
    return System.Convert.ToBase64String(buffer);
}

Також ви можете використовувати дуже хороший онлайн-інструмент OnlineUtility.in для кодування рядка у форматі base64


Інтернет-інструменти не допомагають у цій ситуації - він запитує, як його КОДУВАТИ. Мені часто цікаво, чому люди кажуть "Ознайомтесь з цим інструментом онлайн!", Оскільки ОП не просила онлайн-інструменту: D
Моморо

9
    using System;
    using System.Text;

    public static class Base64Conversions
    {
        public static string EncodeBase64(this string text, Encoding encoding = null)
        { 
            if (text == null) return null;

            encoding = encoding ?? Encoding.UTF8;
            var bytes = encoding.GetBytes(text);
            return Convert.ToBase64String(bytes);
        }

        public static string DecodeBase64(this string encodedText, Encoding encoding = null)
        {
            if (encodedText == null) return null;

            encoding = encoding ?? Encoding.UTF8;
            var bytes = Convert.FromBase64String(encodedText);
            return encoding.GetString(bytes);
        }
    }

Використання

    var text = "Sample Text";
    var base64 = text.EncodeBase64();
    base64 = text.EncodeBase64(Encoding.UTF8); //or with Encoding

4

URL-адреса Base64 Кодування / декодування

public static class Base64Url
{
    public static string Encode(string text)
    {
        return Convert.ToBase64String(Encoding.UTF8.GetBytes(text)).TrimEnd('=').Replace('+', '-')
            .Replace('/', '_');
    }

    public static string Decode(string text)
    {
        text = text.Replace('_', '/').Replace('-', '+');
        switch (text.Length % 4)
        {
            case 2:
                text += "==";
                break;
            case 3:
                text += "=";
                break;
        }
        return Encoding.UTF8.GetString(Convert.FromBase64String(text));
    }
}

1
Питання полягало не в кодуванні URL-адрес, але все-таки корисно ..
Моморо,

Уопс, розмістив його під неправильним запитанням
juliushuck

Немає проблем, все ж цікаво подивитися, як кодувати / декодувати URL-адресу :)
Momoro

3

Ви можете відобразити його так:

var strOriginal = richTextBox1.Text;

byte[] byt = System.Text.Encoding.ASCII.GetBytes(strOriginal);

// convert the byte array to a Base64 string
string strModified = Convert.ToBase64String(byt);

richTextBox1.Text = "" + strModified;

Тепер, перетворюючи його назад.

var base64EncodedBytes = System.Convert.FromBase64String(richTextBox1.Text);

richTextBox1.Text = "" + System.Text.Encoding.ASCII.GetString(base64EncodedBytes);
MessageBox.Show("Done Converting! (ASCII from base64)");

Я сподіваюся, що це допомагає!


1

Для тих, хто просто хоче кодувати / декодувати окремі базові64 цифри:

public static int DecodeBase64Digit(char digit, string digit62 = "+-.~", string digit63 = "/_,")
{
    if (digit >= 'A' && digit <= 'Z') return digit - 'A';
    if (digit >= 'a' && digit <= 'z') return digit + (26 - 'a');
    if (digit >= '0' && digit <= '9') return digit + (52 - '0');
    if (digit62.IndexOf(digit) > -1)  return 62;
    if (digit63.IndexOf(digit) > -1)  return 63;
    return -1;
}

public static char EncodeBase64Digit(int digit, char digit62 = '+', char digit63 = '/')
{
    digit &= 63;
    if (digit < 52)
        return (char)(digit < 26 ? digit + 'A' : digit + ('a' - 26));
    else if (digit < 62)
        return (char)(digit + ('0' - 52));
    else
        return digit == 62 ? digit62 : digit63;
}

Існують різні версії Base64, які не погоджуються щодо того, що використовувати для цифр 62 та 63, тому DecodeBase64Digitможуть допустити декілька з них.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.