Delphi Base64编码/解码及ZLib压缩/解压


本文整理自网络,侵删。

 

 

最近做项目用到Base64编码及ZLib压缩,发现Delphi自带的Base64编码与java的Base64编码不一致,找了很多方法才解决这个问题,在这里来作一些总结:

压缩方法:

StrToBase64(AnsiString(GZCompressStr(str)));  

解压方法:

GZDecompressStr(Base64ToStr(AnsiString(Str)));  

 

ZLib压缩组件下载地址http://www.base2ti.com/ 最新版本1.2.8 https://www.base2ti.com/files/delphizlib.128.zip

Base64编码在网友《Delphi版的Base64转换函数》基础上做了修改

unit Base64;

 

interface

 

uses SysUtils, Classes;

 

type

{$IFDEF UNICODE}

  Base64String = AnsiString;

{$ELSE}

  Base64String = string;

{$ENDIF}

 

// 按源长度SourceSize返回Base64编码所需缓冲区字节数

function Base64EncodeBufSize(SourceSize: Integer): Integer;

// 获取Sourec的Base64编码,Base64Buf必须有足够长度。返回实际编码字节数

function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer; overload;

// 将Source编码为Base64字符串返回

function Base64Encode(const Source; SourceSize: Integer): Base64String; overload;

// 将Source从StartPos开始的Size长度的内容源编码为Base64,写入流Dest。

// Size=0 表示一直编码到文件尾

procedure Base64Encode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;

// 把字符串Str编码为Base64字符串返回

{$IFDEF UNICODE}

function StrToBase64(const Str: AnsiString): Base64String; overload;

function StrToBase64(const Str: string): Base64String; overload;

{$ELSE}

function StrToBase64(const Str: string): Base64String;

{$ENDIF}

 

// 按给定的编码源Source和长度SourceSize计算并返回解码缓冲区所需字节数

function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;

// 将Base64编码源Base64Source解码,Buf必须有足够长度。返回实际解码字节数

function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer; overload;

// 将Source从StartPos开始的Size长度的Base64编码内容解码,写入流Dest。

// Size=0 表示一直解码到文件尾

procedure Base64Decode(Source, Dest: TStream; StartPos: Int64 = 0; Size: Int64 = 0); overload;

// 将Base64编码源Base64Source解码为字符串返回

function Base64Decode(const Base64Source; SourceSize: Integer): Base64String; overload;

// 把Base64字符串Base64Str解码为字符串返回

function Base64ToStr(const Base64Str: Base64String): Base64String;

 

implementation

 

const

  Base64_Chars: array[0..63] of AnsiChar = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

  Base64_Bytes: array[0..79] of Byte =

  (

    62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,

    0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,

    10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,

    0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,

    36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51

  );

 

type

  Base64Proc = function(const Source; SourceSize: Integer; var Buf): Integer;

 

procedure Base64Stream(Source, Dest: TStream; Proc: Base64Proc;

  StartPos, Size: Int64; RBufSize, WBufSize: Integer);

var

  RBuf: array of Byte;

  WBuf: array of Byte;

  RSize, WSize: Integer;

begin

  if (StartPos < 0) or (StartPos >= Source.Size) then Exit;

  Source.Position := StartPos;

  if (Size <= 0) or (Size > Source.Size - Source.Position) then

    Size := Source.Size

  else

    Size := Size + Source.Position;

  SetLength(RBuf, RBufSize);

  SetLength(WBuf, WBufSize);

  while Size <> Source.Position do

  begin

    if RBufSize > Size - Source.Position then

       RBufSize := Size - Source.Position;

    RSize := Source.Read(RBuf[0], RBufSize);

    WSize := Proc(RBuf[0],  RSize, WBuf[0]);

    Dest.Write(WBuf[0], WSize);

  end;

end;

 

function Base64EncodeBufSize(SourceSize: Integer): Integer;

begin

  Result := ((SourceSize + 2) div 3) shl 2;

end;

 

(****************************************************************************

*                                                                           *

* BASE64 Encode hint:                                                       *

*                                                                           *

* addr:            (high) 4 byte     3 byte     2 byte     1 byte (low)     *

* sourec ASCII(3 bytes):            33333333   22222222   11111111          *

* bswap:                 11111111   22222222   33333333   00000000          *

* b4 = Base64_Chars[(source >> 8) & 63]:      [00333333]->44444444          *

* b3 = Base64_Chars[(source >> 14) & 63]:     [00222233]->33333333          *

* b2 = Base64_Chars[(source >> 20) & 63]:     [00112222]->22222222          *

* b1 = Base64_Chars[source >> 26]:            [00111111]->11111111          *

*                        b4 << 24   b3 << 16   b2 << 8    b1                *

* dest BASE64(4 bytes)   44444444   33333333   22222222   11111111          *

*                                                                           *

****************************************************************************)

 

function Base64Encode(const Source; SourceSize: Integer; var Base64Buf): Integer;

asm

    push    ebp

    push    esi

    push    edi

    push    ebx

    mov     esi, eax         // esi = Source

    mov     edi, ecx         // edi = Buf

    mov     eax, edx

    cdq

    mov     ecx, 3

    div     ecx              // edx = SourceSize % 3

    mov     ecx, eax         // ecx = SourceSize / 3

    test    edx, edx

    jz      @@1

    inc     eax              // eax = (SourceSize + 2) / 3

  @@1:

    push    eax

    push    edx

    lea     ebp, Base64_Chars

    jecxz   @Last

    cld

  @EncodeLoop:               //  while (ecx > 0){

    mov     edx, [esi]       //   edx = 00000000 33333333 22222222 11111111

    bswap   edx              //   edx = 11111111 22222222 33333333 00000000

    push    edx

    push    edx

    push    edx

    pop     ebx              //   ebx = edx

    shr     edx, 20

    shr     ebx, 26          //   ebx = 00111111

    and     edx, 63          //   edx = 00112222

    mov     ah, [ebp + edx]  //   *(word*)edi = (Base64_Chars[edx] << 8) |

    mov     al, [ebp + ebx]  //     Base64_Chars[ebx]

    stosw                    //   edi += 2

    pop     edx              //   edx = 11111111 22222222 33333333 00000000

    pop     ebx              //   ebx = edx

    shr     edx, 8

    shr     ebx, 14

    and     edx, 63          //   edx = 00333333

    and     ebx, 63          //   ebx = 00222233

    mov     ah, [ebp + edx]  //   *(word*)edi = (Base64_Chars[edx] << 8) |

    mov     al, [ebp + ebx]  //     Base64_Chars[ebx]

    stosw                    //   edi += 2

    add     esi, 3           //   esi += 3

    loop    @EncodeLoop      // }

  @Last:

    pop     ecx              // ecx = SourceSize % 3

    jecxz   @end             // if (ecx == 0) return

    mov     eax, 3d3d0000h   // preset 2 bytes '='

    mov     [edi], eax

    test    ecx, 2

    jnz     @@3

    mov     al, [esi]        // if (ecx == 1)

    shl     eax, 4           //   eax = *esi << 4

    jmp     @@4

  @@3:

    mov     ax, [esi]        // else

    xchg    al, ah           //   eax = ((*esi << 8) or *(esi + 1)) << 2

    shl     eax, 2

  @@4:

    add     edi, ecx         // edi += ecx

    inc     ecx              // ecx = last encode bytes

  @LastLoop:

    mov     edx, eax         // for (; cex > 0; ecx --, edi --)

    and     edx, 63          // {

    mov     dl, [ebp + edx]  //   edx = eax & 63

    mov     [edi], dl        //   *edi = Base64_Chars[edx]

    shr     eax, 6           //   eax >>= 6

    dec     edi              // }

    loop    @LastLoop

  @end:

    pop     eax

    shl     eax, 2           // return  encode bytes

    pop     ebx

    pop     edi

    pop     esi

    pop     ebp

end;

 

function Base64Encode(const Source; SourceSize: Integer): Base64String;

begin

  SetLength(Result, Base64EncodeBufSize(SourceSize));

  Base64Encode(Source, SourceSize, Result[1]);

end;

 

procedure Base64Encode(Source, Dest: TStream; StartPos: Int64; Size: Int64);

begin

  Base64Stream(Source, Dest, Base64Encode, StartPos, Size, 6144, 8192);

end;

 

{$IFDEF UNICODE}

function StrToBase64(const Str: AnsiString): Base64String;

begin

  Result := Base64Encode(Str[1], Length(Str));

end;

 

function StrToBase64(const Str: string): Base64String;

begin

  Result := StrToBase64(AnsiString(Str));

end;

{$ELSE}

function StrToBase64(const Str: string): Base64String;

begin

  Result := Base64Encode(Str[1], Length(Str));

end;

{$ENDIF}

 

function Base64DecodeBufSize(const Base64Source; SourceSize: Integer): Integer;

asm

    mov     ecx, eax    // ecx = Source + Size

    add     ecx, edx

    mov     eax, edx    // eax = Size / 4 * 3

    shr     edx, 2

    shr     eax, 1

    add     eax, edx

    mov     edx, eax

    jz      @@2

  @@1:

    dec     ecx

    cmp     byte ptr [ecx], 61

    jne     @@2         // if (*--ecx == '=')

    dec     eax         //   eax --

    jmp     @@1

  @@2:                  // return eax: BufSize;  edx: Size / 4 * 3

end;

 

function Base64Decode(const Base64Source; SourceSize: Integer; var Buf): Integer;

asm

    push    ebp

    push    esi

    push    edi

    push    ebx

    mov     esi, eax       // esi = Source

    mov     edi, ecx       // edi = Buf

    mov     ebx, edx

    call    Base64DecodeBufSize

    push    eax            // eax = Base64DecodeBufSize(Source, SourceSize)

    sub     edx, eax       // edx -= eax  // edx: '=' count

    lea     ebp, Base64_Bytes

    shr     ebx, 2         // ebx = SourceSize / 4

    test    ebx, ebx

    jz      @end

    push    edx

    cld

  @DecodeLoop:             // for (; ebx > 0; ebx --; edi += 3)

    mov     ecx, 4         // {

    xor     eax, eax

  @xchgLoop:               //   for (ecx = 4, eax = 0; ecx > 0; ecx --)

    movzx   edx, [esi]     //   {

    sub     edx, 43        //      edx = *(int*)esi - 43

    shl     eax, 6         //      eax <<= 6

    or      al, [ebp + edx]//      al |= Base64_Bytes[edx]

    inc     esi            //      esi ++

    loop    @xchgLoop      //   }

    bswap   eax            //   bswap(eax)

    dec     ebx            //   if (ebx == 1) break

    jz      @Last

    shr     eax, 8         //   eax >>= 8

    stosw                  //   *edi = ax; edi += 2

    shr     eax, 16        //   eax >>= 16

    stosb                  //   *edi++ = al

    jmp     @DecodeLoop    // }

  @Last:

    pop     ecx

    xor     ecx, 3         // ecx = last bytes

  @LastLoop:               // for (; ecx > 0; ecx --)

    shr     eax, 8         // {

    stosb                  //   eax >>= 8; *edi ++ = al

    loop    @LastLoop      // }

  @end:

    pop     eax            // return eax

    pop     ebx

    pop     edi

    pop     esi

    pop     ebp

end;

 

procedure Base64Decode(Source, Dest: TStream; StartPos: Int64; Size: Int64);

begin

  Base64Stream(Source, Dest, Base64Decode, StartPos, Size, 8192, 6144);

end;

 

{$IFDEF UNICODE}

function Base64Decode(const Base64Source; SourceSize: Integer): Base64String;

var

  s: AnsiString;

begin

  SetLength(s, Base64DecodeBufSize(Base64Source, SourceSize));

  Base64Decode(Base64Source, SourceSize, s[1]);

  Result := s;

end;

{$ELSE}

function Base64Decode(const Base64Source; SourceSize: Integer): string;

begin

  SetLength(Result, Base64DecodeBufSize(Base64Source, SourceSize));

  Base64Decode(Base64Source, SourceSize, Result[1]);

end;

{$ENDIF}

 

function Base64ToStr(const Base64Str: Base64String): Base64String;

begin

  Result := Base64Decode(Base64Str[1], Length(Base64Str));

end;

 

end.

相关阅读 >>

Delphi 网卡工作状态检测

Delphi 禁用本地网络连接/启用本地网络连接

Delphi unigrid记录check遍历

Delphi twebbrowser流程讲解及如何判断下载网页成功

Delphi 提取字符串中所有数字

Delphi Delphi写的一个上位机

Delphi货币类型转中文大写金额

Delphi xe10.x 快捷失灵解决办法

Delphi ttask无法传递参数的一个解决方案

Delphi中clientdataset的用法小结

更多相关阅读请进入《Delphi》频道 >>



打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...