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 ...
随机推荐
- Tomcat基础配置和高级配置
********** 第一部分 Tomcat基础配置 *********** 一.Apatch Tomcat 在win下配置 大部分转载自:http://blog.csdn.net/liuhao ...
- UVA 10603 - Fill BFS~
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&c ...
- zynq修改ramdisk文件系统
⑴ 挂载 Ramdisk新建目录 tmp, 并将 uramdisk.image.gz 拷贝至该目录$ cd <WORKDIR>/Filesystem$ mkdir tmp$ cp uram ...
- Ehcache与Memcache的差别
ehcache是纯java编写的.通信是通过RMI方式,适用于基于java技术的项目. memcachedserver端是c编写的.client有多个语言的实现,如c.php(淘宝.sina等各大门户 ...
- kafka集群操作指南
目录 kafka集群操作指南 (一)单机版安装 (二)集群安装 (三)集群启停操作 (四)topic相关的操作 (五)某个broker挂掉,本机器可重启 (六)某个broker挂掉且无法重启,需要其它 ...
- or小计
1.使用or的时候,必须养成两边添加括号,否则结果完全不一样. 2.or条件如果复杂的情况下,可以适当考虑union all改写.
- Delphi的指针(有图,很清楚)
Pointers are like jumps, leading wildly from one part of the data structure to another. Their introd ...
- FOJ (FZU) 1476 矩形的个数 排列组合。
http://acm.fzu.edu.cn/problem.php?pid=1476 Problem Description 在一个3*2的矩形中,可以找到6个1*1的矩形,4个2*1的矩形3个1* ...
- [Recompose] Show a Spinner While a Component is Loading using Recompose
Learn how to use the 'branch' and 'renderComponent' higher-order components to show a spinner while ...
- URAL 1542. Autocompletion 字典树
给你最多10w个单词和相应的频率 接下来最多1w5千次询问 每次输入一个字符串让你从前面的单词中依照频率从大到小输出最多10个以该字符串为前缀的单词 開始把单词建成了字典树 然后每次询问找到全部满足条 ...