类似于在线升级,我要把多个文件压缩,用数据流传送到客户端后解压到固定文件夹,覆盖原文件。
求压缩和解压缩的相关知识或例程。
我现在一点头绪都没有。
求压缩和解压缩的相关知识或例程。
我现在一点头绪都没有。
解决方案 »
- 我是菜鸟!请教not supported by automation object 如何解决呢!?
- 请教一个简单的函数声明,请看内容,在线,马上结分
- delphi8.0怎样连接到sybase数据库,不是本机数据库
- 欢迎武汉的程序员与我联系,共同发展
- 怎样提取表中的字段?
- "select subString(dataA,"+beg+","+num+") as mem from databin where ver='"+newbbh+"'"错在什么地方
- 如何下载网页源文件?谢谢各位啦!
- 求求各位帮我解决吧(关于WH_CBT钩子的问题)
- TIdCoderMD5怎么不正确啊?
- 想学地理信息系统,说搞过GIS?给个源程序学学好吗?
- delphi7安装后lib文件夹下怎么没有OpenGL.pas文件呀?
- ★★★★★★欢迎下载CSDN浏览器!!
目前手机短信息的应用越来越广泛,互联网上提供短信息发送的站点也越来越多,但一些站点的服务并不尽如人意,往往发出去的短信息石沉大海。最可靠的发送方法当然是用手中的手机了,如果设置了状态报告,更能确切知道对方是否收到了此条信息。手机发送尽管比较可靠, 但也存在输入麻烦、效率低的问题。本文介绍一种方法,只要手机能够与电脑相连(通过红外端口或用手机数据线连接串行口,同时手机支持GSM AT指令集),就可以通过自行编制的短信息发送软件,实现短信息的发送。 现在市场上的大多数手机均支持类似于Modem控制的GSM AT指令集,该指令集是由诺基亚、爱立信、摩托罗拉和HP等厂家共同为GSM系统研制的,其中包含了对SMS(Short Message Service)的控制。
GSM AT相关指令的介绍
与SMS有关的GSM AT指令如表1所示:
表1 相关的GSM AT指令
对SMS的控制共有三种实现途径:
Block Mode;
基于AT命令的Text Mode;
基于AT命令的PDU Mode。
Text Mode比较简单,多款诺基亚手机均支持该模式。西门子的手机大多只支持PDU模式,PDU模式是发送或接收手机SMS信息的一种方法,短信息正文经过十六进制编码后被传送。目前,PDU已取代Block Mode,因此本文主要探讨PDU模式的发送。
计算机和手机的通信
本文以西门子 S3568i为例,介绍如何实现短信息的发送。
数据线连接
首先,通过S35/25数据线将手机与电脑串行口相连。然后,打开超级终端,选择直接串行口连接,端口参数设为19200速率、无校验、数据位8、停止位1。
红外线连接
如果使用带红外端口的计算机,可以设置与手机的无线连接。首先确认计算机红外端口已打开,并将手机的红外线和收传真/数据功能打开,对接红外端口,计算机系统托盘上应当出现一个红外设备西门子S35(如果没有安装红外监视器,则不显示)。然后,打开超级终端,选择IrDa上的串行口。
连接测试
点击超级终端工具条上的呼叫按钮,输入AT并回车,屏幕上如果出现OK则表明计算机与手机的连接成功,这时就可以输入各类GSM AT指令了。
如:查询手机厂家,输入AT+CGMI=<CR>,屏幕显示Siemens。
通常情况下,执行测试命令AT+CMGS=?<CR>,如果返回OK,表明手机支持此指令。该指令的完整语法格式如下:
If PDU mode (+CMGF=0)+CMGS=<length><CR>PDU is given <ctrl-Z/ESC>
如果短信息格式指令AT+CMGF返回的是0,则SMS格式为PDU模式,再执行AT+CMGS=<数据长度>命令后,手机返回“>”符号并等待输入,输入PDU数据并以^Z或Esc键结束。
如果信息发送成功,则返回OK,并显示信息号:
+CMGS: <mr>
如果发送失败,则返回如下信息:
+CMS ERROR: <err>
PDU数据格式的分析
下面通过对存储在手机中的待发信息的分析,来介绍SMS PDU的数据格式。首先,用手机写一条短信息,发送手机号码为13605696031,信息内容为“Hello World!”。通过执行AT+CMGL=2可以读出此条信息。
操作过程如下(斜体字符为响应信息,{}内为注释):
AT
OK
AT+CMGL=2 {读未发短信息}
+CMGL: 1,2,,24 {1表示信息个数,2表示未发信息,24表示信息总容量}
08 91 683108501505F0 11 00 0B 81 3106656930F1 0000A7 0B E8329BFD06DDDF723619
OK
下面分析这条信息:
08:短信息中心地址长度。
91:短信息中心号码类型,91是TON/NPI。TON/NPI遵守International/E.164标准,指在号码前需加‘+’号;此外还可有其他数值,但91最常用。
683108501505F0:短信息号码,是所使用的服务中心地址。由于位置上略有处理,实际号码应为:8613805515500(字母F意指长度减1),这是作者所在地GSM短信息中心的号码。
11:文件头字节(header byte,是一种bitmask)。这里11指正常地发送短信息。
00:信息类型。
0B:被叫号码长度。
81:被叫号码类型。
3106656930F1:被叫号码,也经过了移位处理,实际号码为13605696031。
0000A7:短信息编码类型GSM Default Alphabet,如为中文则是000010。
0B:短信息长度。
E8329BFD06DDDF723619:短信息内容“Hello World!”。
短信息的编码方法及编程实现
下面我们介绍纯英文和纯中文的信息编码方法。通过测试我们发现,每条发送的短信息前面部分均相同,只是被叫号码和短信息内容有变化。
1.英文编码
参见表2,设短信息内容为“Hello World!”。缺省的GSM 字符集为7位编码,可以简单地理解为ASCII码(ASCII值小于80Hex,因此,Bit8被忽略),依次将下一7位编码的后几位逐次移至前面,形成新的8位编码,参见表2箭头指示。需要注意的是第9行,移位计数已达7位,则直接将本编码前加0。GSM并非支持所有的ASCII字符显示。
表2 英文编码的实现过程
下面是实现英文编码的部分Delphi 5代码:
//英文格式编码,s为String
function Encode1(var s:String):String;
var
i,j,len:Integer;
cur:Integer;
t:String;
begin
Result:=‘’;
len:=Length(s);
//j 用于移位计数
i:=1;j:=0;
while i<=len do
begin
if i<len then
//数据变换
cur:=(ord(s[i]) shr j) or ((ord(s[i+1]) shl (7-j)) and $ff)
else
cur:=(ord(s[i]) shr j) and $7f;
FmtStr(t,‘%2.2X’,[cur]);
Result:=Result+t;
inc(i);
//移位计数达到7位的特别处理
j:=(j+1) mod 7;if j=0 then inc(i);
end;
end;
2.中文编码
参见表3,设短信息内容为“中文短信息”。中文短信息的实现较简单,只需将GB2312的中文编码转换为代码页为CP936的Unicode编码即可。
表3 中文编码的实现过程
通过Delphi的WideString类型转换,可以巧妙地实现GB2312到Unicode的编码转换(注意代码页和操作系统相关联)。下面是实现中文编码的部分Delphi 5代码:
// 中文格式编码,s为Unicode String
function Encode2(var s:WideString):String;
var
i,len:Integer;
cur:Integer;
t:String;
begin
Result:=‘’;
len:=Length(s);
i:=1;
while i<=len do
begin
cur:=ord(s[i]);
//BCD转换
FmtStr(t,‘%4.4X’,[cur]);
Result:=Result+t;
inc(i);
end;
end;
小 结
以上介绍了PDU格式的短信息编码。建议英文信息长度不超过140个字符,中文信息不要超过54个汉字。如果使用能够支持文本方式的手机进行发送,实现起来更简单。如发送“Hello World!”,用如下的AT指令即可:
AT+CGMF=1<CR>AT+CGMS=“13605696031”,129<CR>
>Hello World!<^Z>
转自:动态网制作指南 www.knowsky.com
其可视化的开发环境和面向对象编程的强大功能已经吸引了无数的开发人员。但是,
一些程序员在实际的开发过程中却时常为对大量的数据进行压缩而伤透脑筋,不得不
去查找一些高效的压缩算法或在网上查找第三方的控件来实现压缩。难道 Delphi本
身没有提供这个功能吗?其实 Delphi的程序设计师早就考虑到了这一点,他们提供了
Zlib.pas和 Zlibconst.pas两个单元文件来解决数据压缩问题,实现了很高的数据
压缩比率。这两个文件保存在 Delphi 5.0安装光盘上 \Info\Extras\Zlib目录下,
此外,在 Info\Extras\Zlib\Obj目录中还保存了 Zlib.pas单元引用的 Obj文件。
下面本文以压缩一个屏幕拷贝为例介绍如何使用这项功能。
解决思路
首先利用屏幕拷贝捕捉到当前整个屏幕的图像,然后在内存中保存为 BMP文件格式。
压缩时,使用 TCompressionStream对象对原始图像进行压缩并且保存为自定义的
文件格式;解压缩时,使用 TDecompressionStream对象对被压缩的图像进行解压缩,
还原为 BMP格式的图像文件。
具体实现
新建一个项目文件,在主单元的接口部分引用 Zlib.pas,在主表单上放置两个按钮
Button1、 Button2,在它们的 OnClick事件中写上相应的过程调用代码。
部分程序源代码如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls, Zlib;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$ R* .DFM}
1.捕捉全屏幕图像
procedure GetScreen(var Bmp: TBitmap);
var
Dc: HDC;
MyCanvas: TCanvas;
MyRect: TRect;
begin
Dc := GetWindowDC(0);
MyCanvas := TCanvas.Create;
try
MyCanvas.Handle := Dc;
MyRect:=Rect(0, 0,Screen.Width, Screen.Height);
//图像为 24位真彩色,也可根据实际需要调整
Bmp.PixelFormat := pf24bit;
Bmp.Width := MyRect.Right;
Bmp.Height := MyRect.Bottom;
//捕捉整个屏幕图像
Bmp.Canvas.CopyRect(MyRect, MyCanvas, MyRect);
finally
MyCanvas.Handle := 0;
MyCanvas.Free;
ReleaseDC(0, Dc);
end;
end;
2.压缩图像
procedure CompressBitmap(var CompressedStream: TMemoryStream;
const CompressionLevel: TCompressionLevel);
var
SourceStream: TCompressionStream;
DestStream: TMemoryStream;
Count: Integer;
Begin
//获得图像流的原始尺寸
Count := CompressedStream.Size;
DestStream := TMemoryStream.Create;
SourceStream:=TCompressionStream.Create
(CompressionLevel, DestStream);
Try
//SourceStream中保存着原始的图像流
CompressedStream.SaveToStream(SourceStream);
//将原始图像流进行压缩, DestStream中保存着压缩后的图像流
SourceStream.Free;
CompressedStream.Clear;
//写入原始图像的尺寸
CompressedStream.WriteBuffer(Count, SizeOf
(Count));
//写入经过压缩的图像流
CompressedStream.CopyFrom(DestStream, 0);
finally
DestStream.Free;
end;
end;
3.还原被压缩图像
procedure UnCompressBitmap(const CompressedStream: TFileStream;
var Bmp: TBitmap);
var
SourceStream: TDecompressionStream;
DestStream: TMemoryStream;
Buffer: PChar;
Count: Integer;
Begin
//从被压缩的图像流中读出原始图像的尺寸
CompressedStream.ReadBuffer(Count, SizeOf(Count));
//根据图像尺寸大小为将要读入的原始图像流分配内存块
GetMem(Buffer, Count);
DestStream := TMemoryStream.Create;
SourceStream := TDecompressionStream.Create(CompressedStream);
Try
//将被压缩的图像流解压缩,然后存入 Buffer内存块中
SourceStream.ReadBuffer(Buffer^, Count);
//将原始图像流保存至 DestStream流中
DestStream.WriteBuffer(Buffer^, Count);
DestStream.Position := 0;//复位流指针
//从 DestStream流中载入原始图像流
Bmp.LoadFromStream(DestStream);
finally
FreeMem(Buffer);
DestStream.Free;
end;
end;
4.压缩按钮 OnClick事件
procedure TForm1.Button1Click(Sender: TObject);
var
Bmp: TBitmap;
CompressedStream: TMemoryStream;
begin
Bmp := TBitmap.Create;
CompressedStream := TMemoryStream.Create;
Try
//捕获当前整个屏幕 ,将图像保存至 Bmp对象中 GetScreen(Bmp);
//将 Bmp对象中的图像保存至内存流中
Bmp.SaveToStream(CompressedStream);
//按缺省的压缩比例对原始图像流进行压缩
CompressBitmap(CompressedStream, clDefault);
//将压缩之后的图像流保存为自定义格式的文件
CompressedStream.SaveToFile(‘ C:\cj.dat’ );
finally
Bmp.Free;
CompressedStream.Free;
end;
end;
5.解压缩按钮 OnClick事件
procedure TForm1.Button2Click(Sender: TObject);
var
CompressedStream: TFileStream;
Bmp: TBitmap;
begin
Bmp := TBitmap.Create;
//以文件流的只读方式打开自定义的压缩格式文件
CompressedStream := TFileStream.Create(‘ C:\cj.dat’ , fmOpenRead);
Try
//将被压缩的图像流进行解压缩
UnCompressBitmap(CompressedStream, Bmp);
//将原始图像流还原为指定的 BMP文件
Bmp.SaveToFile(‘ C:\cj.bmp’ );
finally
Bmp.Free;
CompressedStream.Free;
end;
end;
此外 TCompressionStream对象还提供了 CompressionRate属性,该属性用于描述对
原始数据进行压缩后的压缩比率,而 OnProgress事件在压缩与解压缩过程中都会被
触发,开发人员可以在该事件中编写用于显示进度的代码。
以上代码在 Delphi 5.0中调试运行通过。
procedure CompressStream(SourceStream,DeskStream:TStream);//压缩
var
CompStream:TCompressionStream;
begin
DeskStream.Position :=0;
CompStream:=TCompressionStream.Create(clMax,DeskStream);
SourceStream.Position :=0;
CompStream.CopyFrom(SourceStream,SourceStream.Size);
CompStream.Free;
DeskStream.Position :=0;
end;procedure DeCompressStream(SourceStream, DeskStream: TStream);//解压缩
const
SixK=$ffff;
var
DeCompStream:TDecompressionStream;
Data:array[1..SixK] of Char;
Count:Integer;
begin
SourceStream.Position:=0;
DeCompStream:=TDecompressionStream.Create(SourceStream);
DeskStream.Position :=0;
try
repeat
Count:=DeCompStream.Read(Data,SixK);
if Count>0 then DeskStream.Write(Data,Count);
until Count=0;
finally
DeCompStream.Free;
end;
DeskStream.Position :=0;
end;
请各位大侠帮忙啊
2。另外你也可以用delphi自己做一个程序,让客户自己选择原程序的路径!然后对程序升级
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,Zlib,
StdCtrls;type
TMyFileStruct=record
FileName:String[125];
FileSize:Integer;
end;
TForm1 = class(TForm)
OD: TOpenDialog;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}
procedure CompressStream(SourceStream,DeskStream:TStream);//压缩
var
CompStream:TCompressionStream;
begin
DeskStream.Position :=0;
CompStream:=TCompressionStream.Create(clMax,DeskStream);
SourceStream.Position :=0;
CompStream.CopyFrom(SourceStream,SourceStream.Size);
CompStream.Free;
DeskStream.Position :=0;
end; procedure DeCompressStream(SourceStream, DeskStream: TStream);//解压缩
const
SixK=$ffff;
var
DeCompStream:TDecompressionStream;
Data:array[1..SixK] of Char;
Count:Integer;
begin
SourceStream.Position:=0;
DeCompStream:=TDecompressionStream.Create(SourceStream);
DeskStream.Position :=0;
try
repeat
Count:=DeCompStream.Read(Data,SixK);
if Count>0 then DeskStream.Write(Data,Count);
until Count=0;
finally
DeCompStream.Free;
end;
DeskStream.Position :=0;
end;procedure CompressFiles(FileNames:TStrings;DeskStream:TStream);
var
FileNum,i,CurrentPos:Integer;
FS:TMyFileStruct;
TempStream:TMemoryStream;
FileStream:TFileStream;
begin
TempStream:=TMemoryStream.Create;
FileNum:=FileNames.Count;
DeskStream.WriteBuffer(FileNum,SizeOf(FileNum));
CurrentPos:=FileNum*SizeOf(TMyFileStruct)+SizeOf(FileNum);
for i:=0 to FileNum-1 do
begin
FS.FileName:=ExtractFileName(FileNames[i]);
TempStream.Clear;
FileStream:=TFileStream.Create(FileNames[i],fmShareDenyRead);
CompressStream(FileStream,TempStream);
DeskStream.Position:=i*SizeOf(FS)+SizeOf(FileNum);
FS.FileSize:=TempStream.Size;
DeskStream.WriteBuffer(FS,SizeOf(FS));
DeskStream.Position:=CurrentPos;
CurrentPos:=CurrentPos+DeskStream.CopyFrom(TempStream,0);
FileStream.Free;
end;
TempStream.Free;
end;
procedure DeCompressFiles(DirStr:String;DeskStream:TStream);
var
FileNum,i,CurrentPos:Integer;
FS:TMyFileStruct;
SourceStream,TempStream:TMemoryStream;
begin
TempStream:=TMemoryStream.Create;
SourceStream:=TMemoryStream.Create;
DeskStream.ReadBuffer(FileNum,SizeOf(FileNum));
CurrentPos:=FileNum*SizeOf(FS)+SizeOf(FileNum);
for i:=0 to FileNum-1 do
begin
DeskStream.Position:=i*SizeOf(FS)+SizeOf(FileNum);
DeskStream.ReadBuffer(FS,SizeOf(FS));
SourceStream.Clear;
DeskStream.Position :=CurrentPos;
CurrentPos:=CurrentPos+SourceStream.CopyFrom(DeskStream,FS.FileSize);
TempStream.Clear;
DeCompressStream(SourceStream,TempStream);
TempStream.SaveToFile(DirStr+FS.FileName);
end;
SourceStream.Free;
TempStream.Free;
end;procedure TForm1.Button1Click(Sender: TObject);
var
f:TMemoryStream;
begin
f:=TMemoryStream.Create;
if OD.Execute then
begin
CompressFiles(OD.Files,f);
end;
f.Position:=0;
DeCompressFiles('d:\',f);//测试
end;end.