如何对Base64字符串进行编码和解码?

1316
  1. 如何将一个字符串转换成base64编码的字符串?

  2. 如何将一个base64编码的字符串解码成普通字符串?


8
如果这是一个“分享知识”的问题和答案,我认为我们需要更深入一些的东西。在 SO 上进行快速搜索可以找到:https://dev59.com/UFvUa4cB1Zd3GeqPqSHH#7368168 - Kev
2
请问您真的需要这么做吗?请记住,Base64 主要用于将二进制数据表示为 ASCII,并在字符字段中存储在数据库中或通过电子邮件发送(其中可能会注入新行)。您真的想将字符数据转换为字节,然后再将其转换回字符数据吗?而且这次已经无法阅读并且没有原始编码的提示了。 - bbsimonbb
4
为什么我们应该关注原始编码?我们使用UTF8表示将字符串编码为字节,这可以表示所有可能的字符串字符。然后我们对该数据进行序列化,在另一端进行反序列化并重构与原始字符串相同的字符串(字符串对象无论如何都不保存有关使用的编码信息)。那么为什么编码的使用会引起任何关注呢?我们可以将其视为表示序列化数据的专有方式,我们无论如何都不应该感兴趣。 - Mladen B.
12个回答

2354

编码

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

54
两个函数都进行了输入字符串的空值检查,解决方案完美 :) - Sverrir Sigmundarson
31
那么将它们制作成扩展方法也可以。 - T.J. Crowder
89
为什么要进行空值检查?他并没有引用传入的字符串。空值检查应该是为了在您自己的代码中防止NullReferenceException,而不是防止别人的代码中出现该异常。 - ken
18
@ken还有其他人会说“你应该只暴露自己代码中的错误,而不是别人的”,援引最小惊奇原则,并加上“尽早失败”和“适当的封装”。有时这意味着包装较低级组件的错误,有时则完全不同。在这种情况下,我同意包装deref错误肯定是可疑的(此外,我们都慢慢认识到null作为一个概念本来就有点糟糕),但如果不加检查,我们仍然可以看到一些效果:异常中给出的参数名可能不正确。 - tne
7
返回 System.Text.Encoding.UTF8.GetString(base64EncodedBytes, 0, base64EncodedBytes.Length); 用于 Windows Phone 8。 - steveen zoleko
显示剩余2条评论

171

一行代码:

注意:使用 SystemSystem.Text 指令。

编码:

string encodedStr = Convert.ToBase64String(Encoding.UTF8.GetBytes("inputStr"));

解码:

string inputStr = Encoding.UTF8.GetString(Convert.FromBase64String(encodedStr));

21
谢谢您记得提及名称空间 - 人们总是默认它已经包含在内。 - stimms
3
任何一款专业的集成开发环境都会为您提供这些功能。;) - derHugo
3
如果命名空间位于默认情况下未被引用的程序集中,那么即使是强大的 IDE 也无法帮助 :) - RAPTOR
3
在这种情况下,添加using语句也不会有太大帮助。 - derHugo
3
@derHugo 当然是对的,但如果我们知道命名空间,就可以猜测程序集名称。(至少这帮了我几次忙) - RAPTOR
显示剩余2条评论

61

我分享我的实现,其中包含一些很棒的功能:

  • 使用扩展方法来处理编码类。原因是有人可能需要支持不同类型的编码(不仅仅是UTF8)。
  • 另一个改进是对于空输入返回空结果——在实际情况中非常有用,并且支持X=decode(encode(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);
        }
    }
}

9
如果返回null时,则行为非常不一致,没有其他与字符串一起使用的 .NET API 会这样做。 - t3chb0t
6
@t3chb0t 随意调整它以适应您的需求。因为这里呈现的方式已经根据我们的需要进行了调整。这不是公共API ;) - andrew.fox

49

根据 Andrew Fox 和 Cebe 的回答,我将其改为字符串扩展而不是 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;
        }
    }
}

2
我会添加一个ParseBase64(this string text, Encoding encoding, out string decodedText)方法(以填充必要的异常,并在TryParseBase64上调用它)。 - João Antunes

25

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

16

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

请注意,连续多次使用 Replace()TrimEnd() 将分配新的字符串,这些字符串将立即成为垃圾并被 GC 回收。相反,您可以使用具有指定容量的 StringBuilder 来避免额外的堆分配。 - Lucas

14

您可以使用以下例程将字符串转换为Base64格式

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

你还可以使用非常好的在线工具OnlineUtility.in将字符串编码为base64格式。


2
在线工具在这种情况下没有帮助——他想知道如何编写代码。我经常想知道为什么人们会说“看看这个在线工具!”,因为 OP 没有要求在线工具 :D - Momoro

11
// Encoding
string passw = "tes123";
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(passw);
string pass = System.Convert.ToBase64String(plainTextBytes);

// Normal
var encodedTextBytes = Convert.FromBase64String(pass);
string plainText = Encoding.UTF8.GetString(encodedTextBytes);

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

对于那些只想编码/解码单个base64数字的人:

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可以容忍其中几个。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接