Delphi BASE64单元EncdDecd的修改
Delphi BASE64单元EncdDecd的修改
EncdDecd.pas两个函数声明:
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(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.
Delphi BASE64单元EncdDecd的修改的更多相关文章
- delphi Base64编码/解码及数据压缩/解压知识
一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...
- Delphi Base64编码/解码及ZLib压缩/解压
最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结: 一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDe ...
- Delphi Base64编码_解码及ZLib压缩_解压(转)
最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结:一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然 ...
- 如何隐藏Excel中单元格公式且其他单元格可修改
需求:1.隐藏指定单元格公式.2.非公式单元格可修改,不影响公式计算. 操作步骤:1.全选工作表.右键.单元格格式.保护.锁定勾选取消. 2.编辑.定位(或按F5弹出该对话框).定位条件.公式(勾选) ...
- Delphi 跨单元进入(访问)类的私有成员,protected ,private部分
http://blog.sina.com.cn/s/blog_5f8861b60102v1nl.html Delphi 跨单元进入(访问)类的私有成员,protected ,private部分 (20 ...
- delphi 获取文件的最新修改时间 http://www.delphitop.com/html/wenjian/64.html
delphi 获取文件的最新修改时间 作者:admin 来源:未知 日期:2010/1/28 13:15:22 人气:1054 标签: QQ空间新浪微博腾讯微博腾讯朋友QQ收藏百度空间百度贴吧更多0 ...
- Delphi Base64 编解码函数
Delphi 自带 Base64 编解码的单元, EncdDecd这个单元提供两套四个公开函数: 对流的编解码:procedure EncodeStream(Input, Output: TStrea ...
- Delphi开发的IP地址修改工具
用Delphi进行开发的,直接修改注册表,需重启电脑后才生效
- 手动升级Delphi控件时,修改inc文件的办法
以MustangPeakCommonLib.exe控件为例,想让它支持Delphi2010,就需要在D:\Program Files\Common Library\Mustangpeak\Common ...
随机推荐
- S3C2440 gpio
WATCHDOG TIMER 原理图 手册 举例 start.S .globl _start _start: /* 关看门狗 */ /* 往WTCON(0x53000000)写0 */ ldr r0, ...
- 使用SAP Leonardo上的机器学习服务提取图片的特征向量
要想提取图片的特征向量,首先得知道特征向量是什么. 我们假设这样一个服务场景,技师上门维修某设备,发现上面某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技师掏出自 ...
- Feign报错'xx.FeignClientSpecification', defined in null, could not be registered.
解决: 在application.yml中配置: spring: main: allow-bean-definition-overriding: true 参考:https://blog.csdn.n ...
- Django请求生命周期和ORM
dajngo请求生命周期 django请求生命周期是:当用户在browser点击URL后,在django后台都发生了什么. 请求响应Http 1.发送Http请求 2.服务器接收,根据请求头中url在 ...
- 戴尔 R730 服务器装 server 2016。
服务器里面原装系统是 centos 7 ,服务器快递过来时 我没用root账号,(主要是主管忘了这台服务器用户名密码了). 需要用的系统是 server 2016 我这边就按正常的装机流程装机. 1, ...
- 【OF框架】配置信息Config添加配置和代码调用api
一.配置规范 配置信息全部写在OF.WebShell项目文件config.json中 配置键使用OF.开头,配置格式如下: { "OF.IgnoredUrl": "log ...
- rabbitMq实现延时队列
原文:https://my.oschina.net/u/3266761/blog/1926588 rabbitMq是受欢迎的消息中间件之一,相比其他的消息中间件,具有高并发的特性(天生具备高并发高可用 ...
- js插件讲解_javascript原生日历插件讲解
效果图如下: html代码 <div class="date-control" id="date-control"> <span id=&qu ...
- Visual Studio Code IDE + Docker实现PHP Xdebug调试
一.Docker中安装配置Xdebug 通过phpinfo()输出当前安装的PHP版本信息,将信息拷贝到https://xdebug.org/wizard.php相应输入框中,系统会自动检测并推荐合适 ...
- [CSS] Change the Alignment of a Single Flexed Item with 'align-self'
Inside of a flexed container, a single item can control its own flex with align-self. The possible v ...