在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Delphi BASE64单元EncdDecd的修改 EncdDecd.pas两个函数声明: procedure EncodeStream(Input, Output: TStream); 对于Output参数,如果是TMemoryStream,效率真是太糟糕了,测试发现,编码一个5M多的文件,要十几秒钟! 但如果是TStringStream,只要0.2~0.3秒! WHY? 因为TMemoryStream在不断地调用Write方法,不断地向Windows要求分配内存!从而导致性能下降!而TStringStream和TFileStream则没有这个问题。 怎么办? 可以一次性给TMemoryStream分配好内存空间。假设编码前的字节数为X,那麽编码后的字节数为 (X + 2) div 3 * 4 假设解码前的字节数是X,那麽解码后的字节数约为 (X + 3) div 4 * 3 关于回车换行符的修改,找到下面这段代码: if K > 75 then begin BufPtr[0] := #$0D; // 回车 BufPtr[1] := #$0A; // 换行 Inc(BufPtr, 2); K := 0; end; 每隔76个字符,就强制回车换行。将其注释掉, 因为这其实是没什么用。将修改的单元另存为EncdDecdEx,以后就使用它了。 在编码/解码前对Output参数的TMemoryStream事先设置缓冲区大小,避免分多次向WINDOWS申请内存分配: uses encddecdEx; var Input,Output:TMemoryStream; begin Input:=TMemoryStream.Create; try Input.LoadFromFile('c:\aaa.txt'); Output:=TMemoryStream.Create; try Output.Size:=(Input.Size + 2) div 3 * 4; EncodeStream(Input,Output); finally Output.Free; end; finally Input.Free; end; end; 对D7自带的BASE64单元改造后的源码: /// <author>cxg 2020-2-29</author> { 在编码/解码前对Output参数的TMemoryStream事先设置缓冲区大小,避免分多次向WINDOWS申请内存分配 uses encddecdEx; var Input,Output:TMemoryStream; begin Input:=TMemoryStream.Create; try Input.LoadFromFile('c:\aaa.txt'); Output:=TMemoryStream.Create; try Output.Size:=(Input.Size + 2) div 3 * 4; EncodeStream(Input,Output); finally Output.Free; end; finally Input.Free; end; end; } unit base64; interface uses Classes; procedure EncodeStream(Input, Output: TStream); procedure DecodeStream(Input, Output: TStream); function EncodeString(const Input: string): string; function DecodeString(const Input: string): string; implementation const EncodeTable: array[0..63] of Char = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' + 'abcdefghijklmnopqrstuvwxyz' + '0123456789+/'; DecodeTable: array[#0..#127] of Integer = ( Byte('='), 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 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, 64, 64, 64, 64, 64, 64, 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, 64, 64, 64, 64, 64); type PPacket = ^TPacket; TPacket = packed record case Integer of 0: (b0, b1, b2, b3: Byte); 1: (i: Integer); 2: (a: array[0..3] of Byte); 3: (c: array[0..3] of Char); end; procedure EncodePacket(const Packet: TPacket; NumChars: Integer; OutBuf: PChar); begin OutBuf[0] := EnCodeTable[Packet.a[0] shr 2]; OutBuf[1] := EnCodeTable[((Packet.a[0] shl 4) or (Packet.a[1] shr 4)) and $0000003f]; if NumChars < 2 then OutBuf[2] := '=' else OutBuf[2] := EnCodeTable[((Packet.a[1] shl 2) or (Packet.a[2] shr 6)) and $0000003f]; if NumChars < 3 then OutBuf[3] := '=' else OutBuf[3] := EnCodeTable[Packet.a[2] and $0000003f]; end; function DecodePacket(InBuf: PChar; var nChars: Integer): TPacket; begin Result.a[0] := (DecodeTable[InBuf[0]] shl 2) or (DecodeTable[InBuf[1]] shr 4); NChars := 1; if InBuf[2] <> '=' then begin Inc(NChars); Result.a[1] := Byte((DecodeTable[InBuf[1]] shl 4) or (DecodeTable[InBuf[2]] shr 2)); end; if InBuf[3] <> '=' then begin Inc(NChars); Result.a[2] := Byte((DecodeTable[InBuf[2]] shl 6) or DecodeTable[InBuf[3]]); end; end; procedure EncodeStream(Input, Output: TStream); type PInteger = ^Integer; var InBuf: array[0..509] of Byte; OutBuf: array[0..1023] of Char; BufPtr: PChar; I, J, K, BytesRead: Integer; Packet: TPacket; begin K := 0; repeat BytesRead := Input.Read(InBuf, SizeOf(InBuf)); I := 0; BufPtr := OutBuf; while I < BytesRead do begin if BytesRead - I < 3 then J := BytesRead - I else J := 3; Packet.i := 0; Packet.b0 := InBuf[I]; if J > 1 then Packet.b1 := InBuf[I + 1]; if J > 2 then Packet.b2 := InBuf[I + 2]; EncodePacket(Packet, J, BufPtr); Inc(I, 3); Inc(BufPtr, 4); Inc(K, 4); // if K > 75 then //rem by cxg 每隔76个字符,就强制回车换行。将其注释掉 // begin // BufPtr[0] := #$0D; // BufPtr[1] := #$0A; // Inc(BufPtr, 2); // K := 0; // end; end; Output.Write(Outbuf, BufPtr - PChar(@OutBuf)); until BytesRead = 0; end; procedure DecodeStream(Input, Output: TStream); var InBuf: array[0..75] of Char; OutBuf: array[0..60] of Byte; InBufPtr, OutBufPtr: PChar; I, J, K, BytesRead: Integer; Packet: TPacket; procedure SkipWhite; var C: Char; NumRead: Integer; begin while True do begin NumRead := Input.Read(C, 1); if NumRead = 1 then begin if C in ['0'..'9','A'..'Z','a'..'z','+','/','='] then begin Input.Position := Input.Position - 1; Break; end; end else Break; end; end; function ReadInput: Integer; var WhiteFound, EndReached : Boolean; CntRead, Idx, IdxEnd: Integer; begin IdxEnd:= 0; repeat WhiteFound := False; CntRead := Input.Read(InBuf[IdxEnd], (SizeOf(InBuf)-IdxEnd)); EndReached := CntRead < (SizeOf(InBuf)-IdxEnd); Idx := IdxEnd; IdxEnd := CntRead + IdxEnd; while (Idx < IdxEnd) do begin if not (InBuf[Idx] in ['0'..'9','A'..'Z','a'..'z','+','/','=']) then begin Dec(IdxEnd); if Idx < IdxEnd then Move(InBuf[Idx+1], InBuf[Idx], IdxEnd-Idx); WhiteFound := True; end else Inc(Idx); end; until (not WhiteFound) or (EndReached); Result := IdxEnd; end; begin repeat SkipWhite; { BytesRead := Input.Read(InBuf, SizeOf(InBuf)); } BytesRead := ReadInput; InBufPtr := InBuf; OutBufPtr := @OutBuf; I := 0; while I < BytesRead do begin Packet := DecodePacket(InBufPtr, J); K := 0; while J > 0 do begin OutBufPtr^ := Char(Packet.a[K]); Inc(OutBufPtr); Dec(J); Inc(K); end; Inc(InBufPtr, 4); Inc(I, 4); end; Output.Write(OutBuf, OutBufPtr - PChar(@OutBuf)); until BytesRead = 0; end; function EncodeString(const Input: string): string; var InStr, OutStr: TStringStream; begin InStr := TStringStream.Create(Input); try OutStr := TStringStream.Create(''); try EncodeStream(InStr, OutStr); Result := OutStr.DataString; finally OutStr.Free; end; finally InStr.Free; end; end; function DecodeString(const Input: string): string; var InStr, OutStr: TStringStream; begin InStr := TStringStream.Create(Input); try OutStr := TStringStream.Create(''); try DecodeStream(InStr, OutStr); Result := OutStr.DataString; finally OutStr.Free; end; finally InStr.Free; end; end; end.
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论