C#:Base64 编解码

同系列文章:

/* ----------------------------------------------------------
 * 文件名称:Base64.cs
 * 
 * 作者:秦建辉
 * 
 * MSN:splashcn@msn.com
 * QQ:36748897
 * 
 * 博客:http://www.firstsolver.com/wordpress/
 * 
 * 开发环境:
 *      Visual Studio V2010
 *      .NET Framework 4 Client Profile
 *     
 * 版本历史:
 *      V1.1    2012年08月20日
 *              改进解码算法,字符串中允许任意的空白字符、回车换行符、连字符
 *              
 *      V1.0	2012年05月30日
 *              Base64编解码
 *              
 * 参考资料:
 * 		http://www.openssl.org/
------------------------------------------------------------ */
using System;
using System.IO;
using System.Text;

namespace Splash.Util
{
    /// <summary>
    /// Base64 编解码
    /// </summary>
    public static class Base64
    {
        /// <summary>
        /// Base64编码字符集
        /// </summary>
        private const String DATA_BIN2ASCII = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

        /// <summary>
        /// 将字节数组转换成 Base64 编码字符串
        /// </summary>
        /// <param name="inArray">要转换的字节数组</param>
        /// <returns>转换后的 Base64 编码字符串</returns>
        public static String EncodeBase64String(Byte[] inArray)
        {
            if (inArray == null) return null;

            // 每3个字节转换成4个字符
            Int32 Length = ((inArray.Length + 2) / 3) << 2;
            StringBuilder sb = new StringBuilder(Length);

            Int32 Index = 0;
            for (Int32 i = inArray.Length; i > 0; i -= 3)
            {
                if (i >= 3)
                {	// 将3字节数据转换成4个ASCII字符
                    Byte b0 = inArray[Index++];
                    Byte b1 = inArray[Index++];
                    Byte b2 = inArray[Index++];

                    sb.Append(DATA_BIN2ASCII[b0 >> 2]);
                    sb.Append(DATA_BIN2ASCII[((b0 << 4) | (b1 >> 4)) & 0x3F]);
                    sb.Append(DATA_BIN2ASCII[((b1 << 2) | (b2 >> 6)) & 0x3F]);
                    sb.Append(DATA_BIN2ASCII[b2 & 0x3F]);
                }
                else
                {
                    Byte b0 = inArray[Index++];
                    Byte b1;
                    if (i == 2)
                        b1 = inArray[Index++];
                    else
                        b1 = 0;

                    sb.Append(DATA_BIN2ASCII[b0 >> 2]);
                    sb.Append(DATA_BIN2ASCII[((b0 << 4) | (b1 >> 4)) & 0x3F]);
                    if (i == 1)
                        sb.Append('=');
                    else
                        sb.Append(DATA_BIN2ASCII[(b1 << 2) & 0x3F]);
                    sb.Append('=');
                }
            }

            return sb.ToString();
        }

        // private const Byte B64_ERROR = 0xFF; // 错误字符
        // private const Byte B64_EOLN = 0xF0;  // 换行\n
        // private const Byte B64_CR = 0xF1;	// 回车\r
        // private const Byte B64_EOF = 0xF2;	// 连字符-		
        // private const Byte B64_WS = 0xE0;	// 跳格或者空格(\t、space)
        private const Byte B64_NOT_BASE64 = 0xF3;   // 空白字符、回车换行字符、连字符

        /// <summary>
        /// Base64 编码字符对应的序号列表
        /// </summary>
        private static readonly Byte[] DATA_ASCII2BIN = {
            0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF,
            0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
            0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F,
            0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,
            0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,
            0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF,
            0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,
            0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF	
        };

        /// <summary>
        /// 将 Base64 编码字符串解码为字节数组
        /// </summary>
        /// <param name="base64String">用于解码的 Base64 编码字符串</param>
        /// <returns>解码后的字节数组</returns>
        /// <remarks>
        ///     注意:
        ///         1.字符串中允许任意的空白字符、回车换行符、连字符
        ///         2.微软的Convert.FromBase64String不能处理连字符
        /// </remarks>
        public static Byte[] DecodeBase64(String base64String)
        {
            if (String.IsNullOrEmpty(base64String))
                return null;

            Int32 Length = base64String.Length;
            using (MemoryStream memStream = new MemoryStream(((Length + 3) >> 2) * 3))
            {
                Int32 Index = 0;
                Byte Previous = 0;
                for (Int32 i = 0; i < Length; i++)
                {
                    Int32 CharValue = base64String[i];
                    if (CharValue >= 0x80)
                        throw new ArgumentException();	// 错误字符			

                    Byte OrderValue = DATA_ASCII2BIN[CharValue];
                    if (OrderValue == 0xFF)
                        throw new ArgumentException();	// 错误字符

                    // 跳过空白字符、回车换行字符、连字符
                    if ((OrderValue | 0x13) == B64_NOT_BASE64)
                        continue;

                    if (Index == 0)
                    {
                        if (CharValue == '=')
                            throw new ArgumentException();

                        Previous = OrderValue;
                        Index++;
                    }
                    else if (Index == 1)
                    {
                        if (CharValue == '=')
                            throw new ArgumentException();

                        memStream.WriteByte((Byte)((Previous << 2) | (OrderValue >> 4)));
                        Previous = OrderValue;
                        Index++;
                    }
                    else if (Index == 2)
                    {
                        if (CharValue == '=')
                        {   // 简化处理,不再判断第二个'='
                            Index = 0;
                            break;
                        }

                        memStream.WriteByte((Byte)((Previous << 4) | (OrderValue >> 2)));
                        Previous = OrderValue;
                        Index++;
                    }
                    else
                    {
                        Index = 0;
                        if (CharValue == '=') break;

                        memStream.WriteByte((Byte)((Previous << 6) | OrderValue));
                    }
                } // End for

                // 有效字符个数必须是4的倍数
                if (Index == 0)
                    return memStream.ToArray();
                else
                    throw new ArgumentException();
            }
        }
    }
}

Comments are closed.