Base64 用来将数据编码为可读的字符串。

编码完的结果只包含字母,数字,+,/ ,=

编码完的结果长度是原始值的4/3.

编码原理:

1. 3*8==4*6

  将3字节数据映射到四字节

 

 

编码实现:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Algorithm
{
   public class Base64Algorithm
    {
       const string BaseString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

       static Dictionary<int, char> map=new Dictionary<int,char>();
       static Dictionary<char, int> mapRevert = new Dictionary<char, int>();

      static  Base64Algorithm()
       {
           for (int i = 0; i < BaseString.Length; i++)
           {
               map[i] = BaseString[i];
               mapRevert[BaseString[i]] = i;
           }       
       }

       public string ToBase64String(byte[] src)
       {
           int targetLen = src.Length;
           byte[] buff=null;

           int reminderCount = src.Length % 3;

           if (reminderCount > 0)
           {
               targetLen = src.Length + (3 - reminderCount);
           }
           else
           {
               targetLen = src.Length;
           }

           buff = new byte[targetLen];

           Array.Copy(src, 0, buff, 0,src.Length);          

           StringBuilder sb = new StringBuilder();

           for (int i = 0; i < targetLen / 3; i++)
           {
               char c0 = map[(int)(buff[i*3] >> 2) & 0x3f];
               char c1 = map[(int)((buff[i*3] & 0x03) << 4 | buff[i*3+1] >> 4) & 0x3f];
               char c2 = map[(int)((buff[i*3+1] & 0x0f) << 2 | buff[i*3+2] >> 6) & 0x3f];
               char c3 = map[(int)buff[i*3+2] & 0x3f];

               sb.Append(c0);
               sb.Append(c1);
               sb.Append(c2);
               sb.Append(c3);
           }

           if (reminderCount == 2)
           {
               sb.Remove(sb.Length - 1, 1);
               sb.Append('=');
           }
           else if (reminderCount == 1)
           {
               sb.Remove(sb.Length - 2, 2);
               sb.Append("==");
           }

           return sb.ToString();
       }

       public string FromBase64String(string src)
       {          
           throw new NotImplementedException();
       }
    }
}

 

测试:

/// <summary>
       ///A test for ToBase64String
       ///</summary>
       [TestMethod()]
       public void ToBase64StringTest()
       {
           Base64Algorithm target = new Base64Algorithm(); // TODO: Initialize to an appropriate value
           byte[] src = Encoding.Default.GetBytes("A");
           string expected;
           string actual;

           src = Encoding.ASCII.GetBytes("ABC");
           expected = "QUJD";

           actual = target.ToBase64String(src);
           Assert.AreEqual(expected, actual);


           actual = target.ToBase64String(src);
           Assert.AreEqual(expected, actual);

           src = Encoding.ASCII.GetBytes("AB");
           expected = "QUI=";

           actual = target.ToBase64String(src);
           Assert.AreEqual(expected, actual);

           Random rand=new Random();

           for (int i = 0; i < 99; i++)
           {
               src = new byte[64+i];
               rand.NextBytes(src);

               expected = Convert.ToBase64String(src);
               actual = target.ToBase64String(src);
               Assert.AreEqual(expected, actual);
           }


        
       }

 

 

解码实现:

 

public byte[] FromBase64String(string src)
      {
          int padLen = 0;

          byte[] result = new byte[src.Length * 3 / 4];

          if (src.Length < 4)
          {
              throw new ApplicationException("length is too short.");
          }

          if (src.Length % 4 != 0)
          {
              throw new ApplicationException("length is not valid.");
          }

          for (int i = 0; i < src.Length / 4; i++)
          {
              byte bit0 = Convert.ToByte(mapRevert[src[i * 4]]);
              byte bit1 = Convert.ToByte(mapRevert[src[i * 4 + 1]]);
              byte bit2 = Convert.ToByte(mapRevert[src[i * 4 + 2]]);
              byte bit3 = Convert.ToByte(mapRevert[src[i * 4 + 3]]);

              result[i * 3] = Convert.ToByte((bit0 & 0x3f) << 2 | (bit1 & 0x3f) >> 4);
              result[i * 3 + 1] = Convert.ToByte((bit1 & 0x0f) << 4 | (bit2 & 0x3f) >> 2);
              result[i * 3 + 2] = Convert.ToByte((bit2 & 0x03) << 6 | bit3 & 0x3f);
          }

          if (src[src.Length - 1] == '=' &&
              src[src.Length - 2] != '=')
          {
              padLen = 1;
          }
          else if (src[src.Length - 2] == '=' &&
              src[src.Length - 1] == '=')
          {
              padLen = 2;
          }

          byte[] ret = result.Take(result.Length - padLen).ToArray();

          return ret;
      }

 

解码测试:

/// <summary>
      ///A test for FromBase64String
      ///</summary>
      [TestMethod()]
      public void FromBase64StringTest()
      {
          Base64Algorithm target = new Base64Algorithm(); // TODO: Initialize to an appropriate value           

          byte[] actual;

          actual = target.FromBase64String("QUJD");
          Assert.AreEqual(Encoding.ASCII.GetString(actual), "ABC");

          actual = target.FromBase64String("QUI=");
          Assert.AreEqual(Encoding.ASCII.GetString(actual), "AB");

          actual = target.FromBase64String("QQ==");
          Assert.AreEqual(Encoding.ASCII.GetString(actual), "A");

          Random rand = new Random();

          for (int i = 0; i < 1003; i++)
          {
              byte[] src = null;
              src = new byte[64 + i];
              rand.NextBytes(src);
              //src = Encoding.ASCII.GetBytes("ABCDEFG");
              string srcString = Convert.ToBase64String(src);
              byte[] expectedBytes = Convert.FromBase64String(srcString);

              actual = target.FromBase64String(srcString);
              Assert.AreEqual(expectedBytes.Length, actual.Length);

              for (int j = 0; j < expectedBytes.Length; j++)
              {
                  Assert.AreEqual<byte>(expectedBytes[j], actual[j]);
              }
          }
      }

posted on 2011-07-01 17:54  netfuns  阅读(328)  评论(0编辑  收藏  举报