Delphi Base64编码/解码及ZLib压缩/解压
最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结:
procedure EncodeStream(Input, Output: TStream);
procedure DecodeStream(Input, Output: TStream);
很明了, 两个参数,都为TStream, TStream是抽象类, 其派生类主要有TMomoryStream,TStringStream,TFileStream等,都可以作为参数传递进去,对於Input参数,无论TMemoryStream, TStringStream, TFileStream都不会影响性能,但是对於Output参数,由於压缩的结果是写住OutputStream,因此压缩过程中不断地执行TStream的Write方法,如果是TMemoryStream,那效率真是太糟糕了,我作过测试,编码一个5M多的文件,要十几秒钟!但如果是TStringStream呢,只要0.2~0.3秒! 这究竟是为什麽呢,因为TMemoryStream里不断调用Write方法的结果是,不断地向Windows要求分配内存!从而导致性能下降!而TStringStream和TFileStream则没有这个问题. 因此,在这里极力向朋友们建议,Output参数最好不用TMemoryStream.
不过不要紧,你一定要用的话,也是有方法解决性能下降这个问题的! 因为效率下降的原因是不断的申请内存空间,我们可以从这个方向首手,能不能一次性给它分配好内存空间呢,如果我们事先能确定编码或解码后的数据大小(字节数),那麽这是可行的. 问题的关键就是如何确定这个编码或解码后的字节数了. 对於EncdDecd,我可以给出这个计算方法:
(1)假设编码前的字节数为X,那麽编码后的字节数为 (X + 2) div 3 * 4. 不过,要对EncdDecd进行相应的修改,找到这一小段:
if K > 75 then
begin
BufPtr[0] := #$0D;
BufPtr[1] := #$0A;
Inc(BufPtr, 2);
K := 0;
end;
将其注释掉, 因为这其实是没什麽用的,只是用来对编码后的字符串分行的~,我们可以注释后将单元另存为EncdDecdEx,以后就使用它了!!!
(2)假设解码前的字节数是X,那麽解码后的字节数约为 (X + 3) div 4 * 3
*****注:与编码不同的是,解码的字节数不是确定的,差值在0~2之间.
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;
ZLib;
const
MAXBUFSIZE=1024 * 16; //16 KB
var
CS:TCompressionStream;
DS:TDecompressionStream;
Buf:array[0..MAXBUFSIZE-1] of Byte;
BufSize:Integer;
begin
if Assigned(Input) and Assigned(Output) then
begin
if Compress then
begin
CS:=TCompressionStream.Create(clDefault,Output);
try
CS.CopyFrom(Input,0); //从开始处复制
finally
CS.Free;
end;
end else
begin
DS:=TDecompressionStream.Create(Input);
try
BufSize:=DS.Read(Buf,MAXBUFSIZE);
while BufSize>0 do
begin
Output.Write(Buf,BufSize);
BufSize:=DS.Read(Buf,MAXBUFSIZE);
end;
finally
DS.Free;
end;
end;
end;
end;
var
InputStream,OutputStream:TStringStream;
begin
if Input='' then Exit;
InputStream:=TStringStream.Create(Input);
try
OutputStream:=TStringStream.Create('');
try
Zip(InputStream,OutputStream,Compress);
Result:=OutputStream.DataString;
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
CS:=TCompressionStream.Create(clDefault,Output);
这是在建立压缩类以对流进行压缩, 这里面有个参数clDefault,当然还有其它的选项:clNone, clFastest, clDefault, clMax;
clNone与clFastest就不讨论了,因为不能获得良好的压缩效果,在这里想讨论clDeafult与clMax哪一个好点,我作了一些测试,测试数据如下:
clDefault 2.71M ~1.4s ~937K
5.10M ~2.8s ~1.77M
5.10M ~4.7s ~1.77M
因此,我们可以将其转换成string类型再进行压缩,至於压缩后是以string传输还是转换回VarByte array类型,就由个人决定了. 下面的函数完成将MIDAS数据包转换成string类型.
var
P:Pointer;
Size:Integer;
begin
if not VarIsArray(vData) then Exit;
Size:=VarArrayHighBound(vData,1)-VarArrayLowBound(vData,1)+1;
P:=VarArrayLock(vData);
try
SetLength(Result,Size);
Move(P^,Result[1],Size);
finally
VarArrayUnLock(vData);
end;
end;
var
Command:WideString;
Options:TGetRecordOptions;
RecsOut:Integer;
Params,OwnerData:OleVariant;
begin
try
Command:='SELECT DeptID,DeptNo,DeptName,MasterID FROM Department ORDER BY DeptNo';
Options:=[grReset,grMetaData];
Result:=FCommTDM.AS_GetRecords('CommDsp',-1,RecsOut,Byte(Options),Command,Params,OwnerData);
Result:=UnpackMIDAS(Result); //将MIDAS封包转换成string类型
Result:=Zip(Result,True); //进行压缩,再将压缩后结果转回.
SetComplete;
except
SetAbort;
raise;
end;
end;
var
vData:string;
begin
vData:=DeptCoor.GetDeptData;
vData:=Zip(vData,False); //解压
ClientDataSet1.XMLData:=vData; //注意,这里用的是XMLData,不是Data,否则会报错!!!
end;
四. SOAP系统中压缩后编码:
同样,也给出两个函数,来分别完成这两个过程
var
InputStream,OutputStream:TStringStream;
begin
InputStream:=TStringStream.Create(Input);
try
OutputStream:=TStringStream.Create('');
try
Zip(InputStream,OutputStream,True);
InputStream.Size:=0;
OutputStream.Position:=0; //很重要!!!
EncodeStream(OutputStream,InputStream);
Result:=InputStream.DataString;
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
var
InputStream,OutputStream:TStringStream;
begin
InputStream:=TStringStream.Create(Input);
try
OutputStream:=TStringStream.Create('');
try
DecodeStream(InputStream,OutputStream);
InputStream.Size:=0;
OutputStream.Position:=0; //很重要!!!
Zip(OutputStream,InputStream,False);
Result:=InputStream.DataString;
finally
OutputStream.Free;
end;
finally
InputStream.Free;
end;
end;
Delphi Base64编码/解码及ZLib压缩/解压的更多相关文章
- delphi Base64编码/解码及数据压缩/解压知识
一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然还有第三方提供的单元或控件,其中我所接触到的认为比较好的有Indy的TIdMimeEncode / TIdMimeD ...
- java 字符串zlib压缩/解压
今天在测公司的中间件时发现,增加netty自带的zlib codec压缩处理后,就报decompress failed, invalid head之类的异常.后来发现,直接用bytebuf处理报文体是 ...
- Delphi Base64编码/解码
Uses CnBase64: CnBase64.Base64Encode(Edit1.Text, Psw64);
- zlib压缩解压示例
#include <stdio.h> #include <string.h> #include <assert.h> #include "zlib.h&q ...
- Delphi Base64编码_解码及ZLib压缩_解压(转)
最近在写的程序与SOAP相关,所以用到了一些Base64编码/解码及数据压缩/解压方面的知识. 在这里来作一些总结:一.Base64编码/解码 一般用到的是Delphi自带的单元EncdDecd,当然 ...
- 基于哈夫曼编码的压缩解压程序(C 语言)
这个程序是研一上学期的课程大作业.当时,跨专业的我只有一点 C 语言和数据结构基础,为此,我查阅了不少资料,再加上自己的思考和分析,实现后不断调试.测试和完善,耗时一周左右,在 2012/11/19 ...
- OpenSSL 使用 base64 编码/解码
简述 关于 OpenSSL 的介绍及安装请参见:Windows下编译OpenSSL 下面主要介绍有关 OpenSSL 使用 base64 编码/解码. 简述 编码解码 更多参考 编码/解码 #incl ...
- 利用openssl进行BASE64编码解码、md5/sha1摘要、AES/DES3加密解密
国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html内部邀请码:C8E245J (不写邀请码,没有现金送)国内私 ...
- Javascript中Base64编码解码的使用实例
Javascript为我们提供了一个简单的方法来实现字符串的Base64编码和解码,分别是window.btoa()函数和window.atob()函数. 1 var encodedStr = win ...
随机推荐
- Oracle 12CR2 中alert.log出现大量的 WARNING: too many parse errors 告警
Oracle 12CR2 中alert.log出现大量的 WARNING: too many parse errors 告警 日志如下: 2018-06-24T17:16:21.024586+08 ...
- AE中Identify查询工具的实现
原文 AE中Identify查询工具的实现 主要实现点击查询并闪烁显示,并把查询要素的信息通过DataGridView显示出来,主要用到的接口: IIdentity.IArray.IIdentifyO ...
- 11、V4L2摄像头获取单幅图片测试程序
#根据网上常见的一个测试程序修改而来 by rockie cheng#include <stdio.h>#include <stdlib.h>#include <stri ...
- HDU4911-Inversion
题意:依据题目要求交换相邻的两个元素k次,使得最后剩下的逆序对数最少 思路:假设逆序数大于0,存在0 <= i < n使得交换Ai,Ai+1后逆序数降低1,所求答案就为max(invers ...
- javascrit开发的基本代码结构的
今天看到群里一个demo,简单看了一下. 然后自己就写了一个通用的javascrit开发的基本代码结构的js文件. 代码例如以下: (function($,win){ //定义全局变量对象 var o ...
- TensorFlow on Windows: “Couldn't open CUDA library cudnn64_5.dll”
TensorFlow on Windows: "Couldn't open CUDA library cudnn64_5.dll" 在 windows 下,使用 import te ...
- 多校 hdu
欢迎參加--每周六晚的BestCoder(有米!) Solve this interesting problem Time Limit: 2000/1000 MS (Java/Others) M ...
- [ES7] Handle Errors in Asynchronous Functions
This lesson shows how regular control flow statements such as try/catch blocks can be used to proper ...
- XHTML 结构化:使用 XHTML 重构网站 分类: C1_HTML/JS/JQUERY 2014-07-31 15:58 249人阅读 评论(0) 收藏
http://www.w3school.com.cn/xhtml/xhtml_structural_01.asp 我们曾经为本节撰写的标题是:"XHTML : 简单的规则,容易的方针.&qu ...
- inflate, findViewById与setContentView的区别与联系 分类: H1_ANDROID 2014-04-18 22:54 1119人阅读 评论(0) 收藏
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentV ...