BASE64 编码原理

unit uBase64;

{
 编码原理:
    将3个字节转换成4个字节((3 X 8)=24=(4X6)),先读入3个字节,
    每读一个字节,左移8位,再右移四次,每次6位,这样就有4个
    字节了。
 解码原理:
    将4个字节转换成3个字节,先读入4个6位(用或运算),每次左
    移6位,再右移3次,每次8位,这样就还原了。

 补"="符:
    Base64将3个字节转变为4个字节,因此,编码后的代码量(以
    字节为单位,下同)约比编码前的代码量多了1/3。如果代码量
    正好是3的整数倍,那么恰好多了1/3。但如果不是呢?这个时
    候“=”终于派上用场啦,当代码量不是3的整数倍时,代码量/3的
    余数自然就是2或者1。转换的时候,结果不够6位的用0来补上
    相应的位置,之后再在6位的前面补两个0。转换完空出的结果
    就用就用“=”来补位,总之要保证最后编码出来得字节数是4的
    倍数。

 例子:

    1、当字符串字符个数为3的倍数时;比如字符串“ABC”,其在计算机内存中的
      十六进制表示为$41、$42、$43,十进制表示为“65”“66”“67”;二进制表示
      为01000001  01000010  01000011   将这三个二进制数依次取6bit
      ,010000/01 0100/0010  01/000011  就转换成了:  010000  
      010100  001001  000011  将这四个二进制数转换成十六制数为:
      $10,$14,$9,$3,十进制数位为16,20,9,3。对照上面的码表,分别查
      找出对应的字符为Q,U,J,D。也是就说字符串“ABC”经过BASE64编码后得
      出“QUJD”。  这是最简单的情况,即ASCII码字符数刚好可以被3整除。接
      着继续讨论余数为2、为1的情况。  

    2、当余数为2时,比如字符串“ce”,其在内存中十六进制表示为$63,$65;十
      进制表示表示99,101;二进制表示为  01100011 01100101 依次取6bit
       011000/11 0110/0101  这时,第3个字符不足6位,在后面补零,也就
      是0101变成010100。转换结果为  011000 110110 010100  这3个二进
      制数转换成十六制数为$18,$36,$14;十进制数位为24,54,20。对照码表
      得出结果“Y2U”。编码后的字符个数不足4位,用“=”填充,最后编码得出“Y2U=”。
        
    3、当余数为1时,比如字符串“{”,其在内存中的十六进制表示为$7B,十进制为
      123,二进制位表示为  01111011 依次取6bit 011110/11   补0后为
       011110/110000  转换结果为011110和110000  这两个二进制数转换成
      十六进制数为$1E,$30,十进制数为30,48。对照码表得出结果为“ew”,补上
      “=”,最后编码得出“ew= =”。  解码也很简单,是编码的逆过程,即将每
      个字符对照码表换算成6bit的二进制数,然后重组起来,按8位进行截取,得出原码。

    根据上述原始长度<=3的,转码后长度为4即为 Len/3 向上取整后*4
    当长度3<Len<=6

    Len*8=iLen*6
    iLen mod 4 = 0
    iLen = 4/3 * Len = Len+1/3*Len 比原始字符多了1/3
    

    1个汉字=2个字节 一个字节=8位
}

interface

uses
  Classes,Sysutils;

  function EnCodeBase64(Const srcStr:String;Var Base64DestStr:String):Boolean;
  function DeCodeBase64(Const Base64Str:String;var DestStr:String):Boolean;

implementation
  
const
    B64: array[0..63] of byte= (65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
         81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,
         109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,
         54,55,56,57,43,47);

    //CodeIndex : String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';


function Base64Encode(pInput: pointer; pOutput: pointer; Size: longint): longint;
var
  i, iptr, optr: integer;
  Input, Output: PByteArray;
begin
  Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
  iptr:= 0; optr:= 0;
  for i:= 1 to (Size div 3) do
  begin
     Output^[optr+0]:= B64[Input^[iptr] shr 2];
     Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
     Output^[optr+2]:= B64[((Input^[iptr+1] and 15) shl 2) + (Input^[iptr+2] shr 6)];
     Output^[optr+3]:= B64[Input^[iptr+2] and 63];
     Inc(optr,4); Inc(iptr,3);
  end;
  case (Size mod 3) of
     1: begin
          Output^[optr+0]:= B64[Input^[iptr] shr 2];
          Output^[optr+1]:= B64[(Input^[iptr] and 3) shl 4];
          Output^[optr+2]:= byte('=');
          Output^[optr+3]:= byte('=');
        end;
     2: begin
          Output^[optr+0]:= B64[Input^[iptr] shr 2];
          Output^[optr+1]:= B64[((Input^[iptr] and 3) shl 4) + (Input^[iptr+1] shr 4)];
          Output^[optr+2]:= B64[(Input^[iptr+1] and 15) shl 2];
          Output^[optr+3]:= byte('=');
        end;
  end;
  Result:= ((Size+2) div 3) * 4;
end;

function Base64EncodeStr(const Value: string): string;
begin
  SetLength(Result,((Length(Value)+2) div 3) * 4);
  Base64Encode(@Value[1],@Result[1],Length(Value));
end;

function Base64Decode(pInput: pointer; pOutput: pointer; Size: longint): longint;
var
  i, j, iptr, optr: integer;
  Temp: array[0..3] of byte;
  Input, Output: PByteArray;
begin
  Input:= PByteArray(pInput); Output:= PByteArray(pOutput);
  iptr:= 0; optr:= 0;
  Result:= 0;
  for i:= 1 to (Size div 4) do
  begin
     for j:= 0 to 3 do
     begin
       case Input^[iptr] of
         65..90 : Temp[j]:= Input^[iptr] - Ord('A');
         97..122: Temp[j]:= Input^[iptr] - Ord('a') + 26;
         48..57 : Temp[j]:= Input^[iptr] - Ord('0') + 52;
         43       : Temp[j]:= 62;
         47       : Temp[j]:= 63;
         61       : Temp[j]:= $FF;
       end;
       Inc(iptr);
     end;
     Output^[optr]:= (Temp[0] shl 2) or (Temp[1] shr 4);
     Result:= optr+1;
     if (Temp[2]<> $FF) and (Temp[3]= $FF) then
     begin
       Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
       Result:= optr+2;
       Inc(optr)
     end
     else if (Temp[2]<> $FF) then
     begin
       Output^[optr+1]:= (Temp[1] shl 4) or (Temp[2] shr 2);
       Output^[optr+2]:= (Temp[2] shl 6) or    Temp[3];
       Result:= optr+3;
       Inc(optr,2);
     end;
     Inc(optr);
  end;
end;

function Base64DecodeStr(const Value: string): string;
begin
  SetLength(Result,(Length(Value) div 4) * 3);
  SetLength(Result,Base64Decode(@Value[1],@Result[1],Length(Value)));
end;

function EnCodeBase64(Const srcStr:String;Var Base64DestStr:String):Boolean;
begin
  Result := True;
  try
    Base64DestStr := Base64EncodeStr(srcStr);
  except
    Result := False;
  end;
end;

function DeCodeBase64(Const Base64Str:String;var DestStr:String):Boolean;
begin
  Result := True;
  try
    DestStr := Base64DecodeStr(Base64Str);
  except
    Result := False;
  end;
end;

end.


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

边缘998

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值