Comment encoder et décoder une chaîne base64?

885
  1. Comment renvoyer une chaîne encodée en base64 avec une chaîne?

  2. Comment décoder une chaîne encodée en base64 en une chaîne?

Kevin Driedger
la source
4
S'il s'agit d'une question et d'une réponse de «partage des connaissances», je pense que nous recherchons quelque chose d'un peu plus en profondeur. Une recherche rapide de SO apparaît également: stackoverflow.com/a/7368168/419
Kev
1
@Gnark Toute chaîne est codée par un certain schéma de codage binaire sous-jacent. Que ce soit ASCII, UTF7, UTF8, .... La question posée est au mieux incomplète.
Lorenz Lo Sauer
2
Demandez-vous avez-vous vraiment besoin de faire cela? Rappelez-vous que base64 est principalement destiné à représenter des données binaires en ASCII, à stocker dans un champ char dans une base de données ou à envoyer par e-mail (où de nouvelles lignes pourraient être injectées). Voulez-vous vraiment prendre des données de caractères, les convertir en octets, puis les reconvertir en données de caractères, cette fois illisibles et sans aucune indication de ce qu'était l'encodage d'origine?
bbsimonbb
Pourquoi devrions-nous nous soucier de l'encodage d'origine? Nous encodons la chaîne en octets en utilisant la représentation UTF8, qui peut représenter tous les caractères de chaîne possibles. Nous sérialisons ensuite ces données et à l'autre extrémité, nous désérialisons ces données et nous reconstruisons la même chaîne que nous avions à l'origine (l'objet chaîne ne contient pas les informations sur l'encodage utilisées de toute façon). Alors, pourquoi y a-t-il des problèmes liés au codage utilisé? Nous pouvons le considérer comme une manière exclusive de représenter les données sérialisées, ce qui ne devrait en aucun cas nous intéresser.
Mladen B.

Réponses:

1668

Encoder

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

Décoder

public static string Base64Decode(string base64EncodedData) {
  var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
  return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
Kevin Driedger
la source
41
Null vérifie les chaînes d'entrée dans les deux fonctions et la solution est parfaite :)
Sverrir Sigmundarson
22
@SverrirSigmundarson: Cela ou en faire des méthodes d'extension.
TJ Crowder
73
@SverrirSigmundarson - Pourquoi faire une vérification nulle? Ce n'est pas lui qui déréférence la chaîne d'entrée. Les contrôles nuls devraient empêcher NullReferenceExceptiondans votre propre code, pas dans celui de quelqu'un d'autre.
ken
16
@ken Et quelqu'un d'autre dira "vous ne devez exposer que les erreurs dans votre propre code, pas celles de quelqu'un d'autre", invoquant le principe de la moindre surprise, épicé avec "échec précoce" et "encapsulation appropriée". Parfois, cela signifie encapsuler les erreurs des composants de niveau inférieur, parfois autre chose entièrement. Dans ce cas, je conviens que le wrapping d'une erreur deref est certainement douteux (en plus, nous sommes tous d'accord lentement sur le fait que null en tant que concept est un peu un hack pour commencer), mais nous pouvons toujours voir certains effets sinon: le nom du paramètre donné dans l'exception peut ne pas être correct s'il n'est pas coché.
TNE
6
return System.Text.Encoding.UTF8.GetString (base64EncodedBytes, 0, base64EncodedBytes.Length); pour windows phone 8
steveen zoleko
46

Je partage mon implémentation avec quelques fonctionnalités intéressantes:

  • utilise des méthodes d'extension pour la classe Encoding. La justification est que quelqu'un peut avoir besoin de prendre en charge différents types d'encodages (pas seulement UTF8).
  • Une autre amélioration échoue gracieusement avec un résultat nul pour une entrée nulle - il est très utile dans les scénarios réels et prend en charge l'équivalence pour X = décoder (encoder (X)).

Remarque: N'oubliez pas que pour utiliser la méthode d'extension, vous devez (!) Importer l'espace de noms avec un usingmot-clé (dans ce cas using MyApplication.Helpers.Encoding).

Code:

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);
        }
    }
}

Exemple d'utilisation:

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);
        }
    }
}
andrew.fox
la source
5
Le retour nullen cas de nullest un comportement très incohérent. Aucune autre API .net qui fonctionne avec des chaînes ne fait cela.
t3chb0t
4
@ t3chb0t n'hésitez pas à l'adapter à vos besoins. Comme la façon dont elle est présentée ici a été ajustée à la nôtre. Ce n'est pas une API publique;)
andrew.fox
1
N'avez-vous pas maintenant à envoyer 2 variables à l'autre partie de votre communication (à qui vous envoyez des données encodées en base64)? Vous devez envoyer à la fois l'encodage utilisé et les données réelles en base64? N'est-il pas plus facile si vous utilisez une convention des deux côtés d'utiliser le même encodage? De cette façon, vous n'auriez qu'à envoyer des données base64, non?
Mladen B.
38

Sur la base des réponses d'Andrew Fox et de Cebe, je l'ai inversé et leur ai fait des extensions de chaîne au lieu des extensions 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;
        }
    }
}
j2associates
la source
1
J'ajouterais un ParseBase64 (ce texte de chaîne, le codage d'encodage, la chaîne decodedText) (pour remplir l'exception si nécessaire, et l'appeler sur TryParseBase64
João Antunes
22

Une légère variation sur la réponse d'andrew.fox, car la chaîne à décoder peut ne pas être une chaîne encodée en base64 correcte:

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;   
            }
        }
    }
}
Cebe
la source
13

Vous pouvez utiliser la routine ci-dessous pour convertir une chaîne au format base64

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

Vous pouvez également utiliser un très bon outil en ligne OnlineUtility.in pour coder une chaîne au format base64

chaphekar chétan
la source
Les outils en ligne n'aident pas dans cette situation - il demande comment le coder. Je me demande souvent pourquoi les gens disent "Découvrez cet outil en ligne!", Parce que le PO n'a pas demandé un outil en ligne: D
Momoro
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);
        }
    }

Usage

    var text = "Sample Text";
    var base64 = text.EncodeBase64();
    base64 = text.EncodeBase64(Encoding.UTF8); //or with Encoding
Sameera R.
la source
4

Encodage / décodage Base64 sûr pour les URL

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));
    }
}
juliushuck
la source
1
La question n'était pas sur le codage d'URL, mais toujours utile ..
Momoro
Oups, l'a affiché sous la mauvaise question
juliushuck
Pas de problème, c'est quand même intéressant de voir comment encoder / décoder une URL :)
Momoro
3

Vous pouvez l'afficher comme ceci:

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;

Maintenant, reconvertissez-le.

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

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

J'espère que ça aide!

Momoro
la source
1

Pour ceux qui veulent simplement encoder / décoder des chiffres base64 individuels:

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;
}

Il existe différentes versions de Base64 qui ne sont pas d'accord sur ce qu'il faut utiliser pour les chiffres 62 et 63, donc DecodeBase64Digitpeuvent en tolérer plusieurs.

Qwertie
la source