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 ...
随机推荐
- jmeter--基本组件介绍
一.JMeter 介绍 Apache JMeter是100%纯Java桌面应用程序,被设计为用于测试客户端/服务端结构的软件(例如web应用程序).它可以用来测试静态和动态资源的性能,例如:静态文件, ...
- 【高德地图API】从零開始学高德JS API(五)路线规划——驾车|公交|步行
先来看两个问题:路线规划与导航有什么差别?步行导航与驾车导航有什么差别? 回答: 1.路线规划,指的是为用户提供3条路线推荐.[高德]在提供路线规划的时候,会提供用户自己定义路线规划功能,这是别家没有 ...
- apache与IIS共用80端口冲突解决方法
如果同一台电脑安装了apache和iis,会提示80端口冲突,如何解决apache与iis 80端口冲突的问题呢,并且同时使用apache和iis 将apache设为使用80端口,IIS使用其它端口, ...
- wepy小程序实现列表分页上拉加载(1)
使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 列表页效果图: 1.新建列表页 (1)在pages里面新建一个list.wpy文件 初始代码 ...
- mysql数据库各存储引擎比較
mysql数据库差别于其它数据库的最重要的一个特点是其插件式的表存储引擎,存储引擎是基于表的.而不是数据库 InnoDB存储引擎: 支持事务,其设计目标主要面向在线事务处理(OLTP)的 ...
- Redis Cluster(Redis 3.X)设计要点
Redis 3.0.0 RC1版本号10.9号公布,Release Note这个版本号支持Redis Cluster.相信非常多同学期待已久,只是这个版本号仅仅是RC版本号,要应用到生产环境,还得等等 ...
- iOS Objc Runtime 教程+实例Demo
样例Demo 欢迎给我star!我会继续分享的. 概述 Objc Runtime使得C具有了面向对象能力,在程序执行时创建,检查.改动类.对象和它们的方法.Runtime是C和汇编编写的,这里http ...
- 35、在JZ2440上使用3G上网卡
1. 简单使用:1.1 选型:中国联通:E网时空 EW65 (64元), ZTE中兴 MF637U (160多)中国电信:Benton/本腾 EQ10B (35元)中国移动:华为 ET128 (99元 ...
- 【rlz03】十六进制转十进制
Time Limit: 3 second Memory Limit: 2 MB 问题描述 输入一个十六进制数,编程转换为十进制数. 整数部分不会超过65535,十六进制的小数部分不会超过2位. Sam ...
- JNI——Java调用C/C++函数
从C/C++到Java,再从Java回到C/C++,今天终于有机会了解了连接Java.C/C++的桥梁——JNI.哈哈!分享一下! 一.简介 JNI是Java native interface的简 ...