那位大哥可以给我一个高效率的Base64编码解码函数啊(50分)

  • 主题发起人 Linux2002
  • 开始时间
L

Linux2002

Unregistered / Unconfirmed
GUEST, unregistred user!
Indy控件的编码解码函数有问题,我编码一个276KB的文件可以编码,但是解码有问题,无法
解码,自己写的效率过低,没有办法只有求各位老大给个效率高点的函数了
 
我觉得Indy控件中的编码与解码函数没有问题,我一直在用的效率也很高。
我这里有Base64的相关函数我想对你有用。
========================================

Const
Base64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';


Function Base64Encode(Value : String) : String;
Var AIn : Array[1..3] Of Byte;
AOut : Array[1..4] Of Byte;
AWork : Array[1..3] Of Byte;
I : Integer;
O : LongInt;
Begin
Result := '';
I := 1;
O := Length(Value);
Case Length(Value) Mod 3 Of
1 : Value := Value + #0 + #0;
2 : Value := Value + #0;
End;
While I < Length(Value) Do
Begin
AIn[1] := Byte(Value);
AIn[2] := Byte(Value[I+1]);
AIn[3] := Byte(Value[I+2]);

AOut[1] := Byte(AIn[1] Shr 2);
AWork[1] := Byte(AIn[1] Shl 4);
AWork[2] := Byte(AWork[1] And $30);
AWork[3] := Byte(AIn[2] Shr 4);
AOut[2] := Byte(AWork[2] Or AWork[3]);
AWork[1] := Byte(AIn[2] Shl 2);
AWork[2] := Byte(AWork[1] And $3C);
AWork[3] := Byte(AIn[3] Shr 6);
AOut[3] := Byte(AWork[2] Or AWork[3]);
AOut[4] := Byte(AIn[3] And $3F);

Inc(I, 3);
Result := Result + Base64Table[AOut[1]+1] + Base64Table[AOut[2]+1] + Base64Table[AOut[3]+1] + Base64Table[AOut[4]+1];
End;
If O Mod 3 > 0 Then
Result[Length(Result)] := '=';
If O Mod 3 = 1 Then
Result[Length(Result)-1] := '=';
End;

Function Base64Decode(Value : String) : String;
Var AIn : Array[1..4] Of Byte;
AOut : Array[1..3] Of Byte;
AWork : Array[1..3] Of Byte;
I : Integer;
C : Integer;
Begin
Result := '';
I := 1;
While I < Length(Value) Do
Begin
C := 3;
FillChar(AWork, SizeOf(AWork), #0);
FillChar(AOut, SizeOf(AWork), #0);
AIn[1] := Byte(Pos(Value,Base64Table)-1);
AIn[2] := Byte(Pos(Value[I+1],Base64Table)-1);
AIn[3] := Byte(Pos(Value[I+2],Base64Table)-1);
AIn[4] := Byte(Pos(Value[I+3],Base64Table)-1);
If Value[I+3]='=' Then
Begin
C := 2;
AIn[4] := 0;
If Value[I+2]='=' Then
Begin
C := 1;
AIn[3] := 0;
End;
End;
AWork[2] := Byte(AIn[1] Shl 2);
AWork[3] := Byte(AIn[2] Shr 4);
AOut[1] := Byte(AWork[2] Or AWork[3]);
AWork[2] := Byte(AIn[2] Shl 4);
AWork[3] := Byte(AIn[3] Shr 2);
AOut[2] := Byte(AWork[2] Or AWork[3]);
AWork[2] := Byte(AIn[3] Shl 6);
AOut[3] := Byte(AWork[2] Or AIn[4]);
Result := Result + Char(AOut[1]);
If C > 1 Then
Result := Result + Char(AOut[2]);
If C > 2 Then
Result := Result + Char(AOut[3]);
Inc(I, 4);
End;
End;

========================================
 
老兄,您的函数效率比我的还要低啊
 
我有一個,不過你給分也挺少的.
unit uBase64Codec;
interface

function CalcEncoderSize(InSize: Cardinal): Cardinal;

procedure Base64Encode(const InBuffer; InSize: Cardinal; var OutBuffer); overload; register;

procedure Base64Encode(const InText: PAnsiChar; var OutText: PAnsiChar); overload;
procedure Base64Encode(const InText: AnsiString; var OutText: AnsiString); overload;

implementation

uses
SysUtils;

function CalcEncoderSize(InSize: Cardinal): Cardinal;
begin
// no buffers passed along, calculate outbuffer size needed
Result := (InSize div 3) shl 2;
if InSize mod 3 > 0 then
Inc(Result, 4);
end;

procedure Base64Encode(
const InBuffer; InSize: Cardinal; var OutBuffer
); register;
const
cBase64Codec: array[0..63] of AnsiChar =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
var
ByThrees, LeftOver: Cardinal;
// reset in- and outbytes positions
asm
// load addresses for source and destination
// PBYTE(InBuffer);
mov ESI, [EAX]
// PBYTE(OutBuffer);
mov EDI, [ECX]
// ByThrees := InSize div 3;
// LeftOver := InSize mod 3;
// load InSize (stored in EBX)
mov EAX, EBX
// load 3
mov ECX, $03
// clear upper 32 bits
xor EDX, EDX
// divide by ECX
div ECX
// save result
mov ByThrees, EAX
// save remainder
mov LeftOver, EDX
// load addresses
lea ECX, cBase64Codec[0]
// while I < ByThrees do
// begin
xor EAX, EAX
xor EBX, EBX
xor EDX, EDX
cmp ByThrees, 0
jz @@LeftOver
@@LoopStart:
// load the first two bytes of the source triplet
LODSW
// write Bits 0..5 to destination
mov BL, AL
shr BL, 2
mov DL, BYTE PTR [ECX + EBX]
// save the Bits 12..15 for later use [1]
mov BH, AH
and BH, $0F
// save Bits 6..11
rol AX, 4
and AX, $3F
mov DH, BYTE PTR [ECX + EAX]
mov AX, DX
// store the first two bytes of the destination quadruple
STOSW
// laod last byte (Bits 16..23) of the source triplet
LODSB
// extend bits 12..15 [1] with Bits 16..17 and save them
mov BL, AL
shr BX, 6
mov DL, BYTE PTR [ECX + EBX]
// save bits 18..23
and AL, $3F
xor AH, AH
mov DH, BYTE PTR [ECX + EAX]
mov AX, DX
// store the last two bytes of the destination quadruple
STOSW
dec ByThrees
jnz @@LoopStart
@@LeftOver:
// there are up to two more bytes to encode
cmp LeftOver, 0
jz @@Done
// clear result
xor EAX, EAX
xor EBX, EBX
xor EDX, EDX
// get left over 1
LODSB
// load the first six bits
shl AX, 6
mov BL, AH
// save them
mov DL, BYTE PTR [ECX + EBX]
// another byte ?
dec LeftOver
jz @@SaveOne
// save remaining two bits
shl AX, 2
and AH, $03
// get left over 2
LODSB
// load next 4 bits
shl AX, 4
mov BL, AH
// save all 6 bits
mov DH, BYTE PTR [ECX + EBX]
shl EDX, 16
// save last 4 bits
shr AL, 2
mov BL, AL
// save them
mov DL, BYTE PTR [ECX + EBX]
// load base 64 'no more data flag'
mov DH, '='
jmp @@WriteLast4

@@SaveOne:
// adjust the last two bits
shr AL, 2
mov BL, AL
// save them
mov DH, BYTE PTR [ECX + EBX]
shl EDX, 16
// load base 64 'no more data flags'
mov DH, '='
mov DL, '='
// ignore jump, as jump reference is next line !
// jmp @@WriteLast4

@@WriteLast4:
// load and adjust result
mov EAX, EDX
ror EAX, 16
// save it to destination
STOSD
@@Done:
end;

procedure Base64Encode(const InText: PAnsiChar; var OutText: PAnsiChar);
var
InSize, OutSize: Cardinal;
begin
// get size of source
InSize := Length(InText);
// calculate size for destination
OutSize := CalcEncoderSize(InSize);
// reserve memory
OutText := StrAlloc(Succ(OutSize));
OutText[OutSize] := #0;
// encode !
Base64Encode(InText, InSize, OutText);
end;

procedure Base64Encode(const InText: AnsiString; var OutText: AnsiString); overload;
var
InSize, OutSize: Cardinal;
PIn, POut: Pointer;
begin
// get size of source
InSize := Length(InText);
// calculate size for destination
OutSize := CalcEncoderSize(InSize);
// prepare string length to fit result data
SetLength(OutText, OutSize);
PIn := @InText[1];
POut := @OutText[1];
// encode !
Base64Encode(PIn, InSize, POut);
end;

end.

 
帖子不能加分吗?
 
Delphi SOAP 里面有个单元是 EncdDecd,Indy 也有函数,比如 Email 附件的 Base64 MIME
编码单元,JCL (JEDI Code Libarary jcl.sourceforge.net) 也有 JclMime 单元(我喜欢用它),
这么多选择,还问个什么东西
 
随便下载个控件得了多的是。
 
我的還不夠高效嗎?
 
够牛
竟然用asm!!!
不过用Delphi写位操作太痛苦了
还是C来得爽
 
多人接受答案了。
 
顶部