• BASE64算法原理解析之C#实现


    1. BASE64算法原理:

    base64编码规则

         A.采用64个基本的ASCII码字符对数据进行重新编码

        B.将要编码字符串拆分成字节数组,以3个字节为一组按顺序排列24 位数据

       C.把24位数据分成4组,每组6位,每组最高位前补两个0凑足一个字节,

            3字节为一组的数据重新编码成4个字节数据

       D.若编码的数据的字节数不能被3整除,即最后一组不足3字节,

            为最后一组填充1到2个0字节,编码完成后在结尾添加1到2个 “=”,

            补多少个0,就加多少个=

    编码示例

    BASE编码思路:

    1. 取字符串的ASCII码整数值

    2.转换字符串ASCII码整数值为二进制

    3.创建一个3字节数组,每次取字符串3个字节,如果不足用0填充

    4.最后将上面的3字节数组全部转换为二进制字符串并接成24位数据(1字节8位) 

    5.将上面的24位数据分割成4组,每组取6位,然后在最左边加上2个0变成一个8位,相当一个字节

    6.将上面补全8位的四组都转换为字节,最后转换成整数,根据整数去base64字符表取对应索引字符,

       第3步补0的不用取,直接返回=号

    7.如果上面第3步补多少个0,最后编码补一样多的=

    下面是完整的C#代码:

    1. var bytes = Encoding.ASCII.GetBytes("A");//字符串转换位集合
    2. Console.WriteLine("字符串长度:{0}",bytes.Length);//字符串长度
    3. Console.WriteLine("A的ASCII码: {0}",(int)bytes[0]);//字符位转换整数
    4. Console.WriteLine("byte转char: {0}",(char)bytes[0]);//整数转换字符位
    5. string b = Convert.ToString((int)bytes[0], 2).PadLeft(8, '0');//整数转换为二进制
    6. Console.WriteLine("A的ASCII码转换为二进制:{0} ",b);
    7. //8位转6位
    8. var baseBytes = new byte[3];
    9. Console.WriteLine("默认8转6转换位:{0},{1},{2}", baseBytes[0], baseBytes[1], baseBytes[2]);
    10. baseBytes[0] = bytes[0];
    11. var b0 = Convert.ToString((int)baseBytes[0], 2).PadLeft(8, '0');
    12. var b1 = Convert.ToString((int)baseBytes[1], 2).PadLeft(8, '0');
    13. var b2 = Convert.ToString((int)baseBytes[2], 2).PadLeft(8, '0');
    14. Console.WriteLine("填充数据后:{0},{1},{2}",b0,b1,b2);
    15. var threeBitsString = b0 + b1 + b2;
    16. Console.WriteLine("拼接3个8位二进制数据: {0}", threeBitsString);//010000 010000 000000 000000
    17. //转换成4个6位,然后转换成整数
    18. var p1 = threeBitsString.Substring(0,6);
    19. var p2 = threeBitsString.Substring(6, 6);
    20. var p3 = threeBitsString.Substring(12,6);
    21. var p4 = threeBitsString.Substring(18,6);
    22. Console.Write("转换成4个6位: {0}-{1}-{2}-{3}\n", p1,p2,p3,p4);
    23. Console.WriteLine("BASE64: {0}{1}{2}{3}",alph[Convert.ToInt32(p1,2)], alph[Convert.ToInt32(p2, 2)],"=","=");

    BASE64编码多个字符完整源码:

    1. ///
    2. /// 字符串转换成二进制拼接字符串
    3. ///
    4. ///
    5. ///
    6. static String Base64Encode(String toEncodeString)
    7. {
    8. var byteArray = Encoding.ASCII.GetBytes(toEncodeString);
    9. int len = toEncodeString.Length;
    10. var s = new StringBuilder();
    11. var t = new StringBuilder();
    12. var base64Str = string.Empty;
    13. //取满足3字节,先编码
    14. for (int i = 0; i < len/3; i++)
    15. {
    16. var b1 = byteArray[i * 3]; //第1个字节
    17. var b2 = byteArray[i * 3+1]; //第2个字节
    18. var b3 = byteArray[i * 3+2]; //第3个字节
    19. s.Append(Convert.ToString((int)b1, 2).PadLeft(8, '0'));
    20. s.Append(Convert.ToString((int)b2, 2).PadLeft(8, '0'));
    21. s.Append(Convert.ToString((int)b3, 2).PadLeft(8, '0'));
    22. var data = s.ToString();
    23. s.Clear();
    24. //转换成4个6位,然后转换成整数
    25. var p1 = data.Substring(0, 6);
    26. var p2 = data.Substring(6, 6);
    27. var p3 = data.Substring(12, 6);
    28. var p4 = data.Substring(18, 6);
    29. //编码一组3个字节为4字节
    30. base64Str = alph[Convert.ToInt32(p1, 2)].ToString() + alph[Convert.ToInt32(p2, 2)].ToString() +
    31. alph[Convert.ToInt32(p3, 2)].ToString() + alph[Convert.ToInt32(p4, 2)].ToString();
    32. t.Append(base64Str);
    33. }
    34. //处理不足3字节数据
    35. if (len % 3 > 0)
    36. {
    37. var lastGroupLen = len % 3;
    38. var tmpBytes = new byte[3];
    39. if (lastGroupLen == 1)
    40. {
    41. tmpBytes[0] = byteArray[len-1];
    42. tmpBytes[1] = 0;
    43. tmpBytes[2] = 0;
    44. }
    45. if (lastGroupLen == 2)
    46. {
    47. tmpBytes[0] = byteArray[len - 2];
    48. tmpBytes[1] = byteArray[len - 1];
    49. tmpBytes[2] = 0;
    50. }
    51. s.Append(Convert.ToString((int)tmpBytes[0], 2).PadLeft(8, '0'));
    52. s.Append(Convert.ToString((int)tmpBytes[1], 2).PadLeft(8, '0'));
    53. s.Append(Convert.ToString((int)tmpBytes[2], 2).PadLeft(8, '0'));
    54. var data = s.ToString();
    55. s.Clear();
    56. //转换成4个6位,然后转换成整数 //011001 000000 000000 000000 16 + 8 +1 =25
    57. var p1 = data.Substring(0, 6);
    58. var p2 = data.Substring(6, 6);
    59. var p3 = data.Substring(12, 6);
    60. var p4 = data.Substring(18, 6);
    61. if (lastGroupLen==1)
    62. {
    63. //编码一组3个字节为4字节
    64. base64Str = alph[Convert.ToInt32(p1, 2)].ToString() +
    65. alph[Convert.ToInt32(p2, 2)].ToString() + "==";
    66. }
    67. if (lastGroupLen == 2)
    68. {
    69. //编码一组3个字节为4字节
    70. base64Str = alph[Convert.ToInt32(p1, 2)].ToString() +
    71. alph[Convert.ToInt32(p2, 2)].ToString() +
    72. alph[Convert.ToInt32(p3, 2)].ToString() + "=";
    73. }
    74. t.Append(base64Str);
    75. }
    76. Console.WriteLine("StingToBinary: source: {0} -> target: {1}",toEncodeString,t.ToString());
    77. return t.ToString();
    78. }

     

  • 相关阅读:
    《计算机体系结构》1.4 技术趋势
    面试官:来说说vue3是怎么处理内置的v-for、v-model等指令?
    Java8 根据List实体中一个字段去重取最大值,并且根据该字段进行排序
    带头结点的双向链表操作
    Oracle物化视图(Materialized View)
    Croissant:Google新推出的一个为机器学习准备的数据集元数据格式
    环境变量与Path环境变量
    ElementUI之el-progress动态修改进度条里面文本颜色与进度条色块统一
    VL36-状态机-重叠序列检测;设计一个状态机,用来检测序列1011.
    K8s 环境下. DataGrip连接 kerberos认证的hive
  • 原文地址:https://blog.csdn.net/fittec/article/details/126582413