契机:一位朋友的求助。
目的:通过串口传输XML文件。
开发平台:Delphi7
核心组件:SPComm
发送端:
const //申明长度和简单的协议头、尾标识常量
LEN_FILENAME = 255;
MAX_LENGTH = 1024;
MARK_HEAD = '#MYFILE#%s';
MARK_END = '#END#';
{
发送文件
aFile - 文件名
aDelay - 发送延时,给接收端以足够的处理时间,在实际应用时通过经验调节
comm: 用来发送数据的SPComm串口对象,在调用该方法前请确保comm已经打开(StartComm)。
}
procedure sendFile(aFile: string; aDelay: integer; comm: TComm);
var fs: TFileStream; //以流的方式读文件
ss, fn: string; //文件名处理变量
buf: array[1 .. MAX_LENGTH] of char; //用于读取文件数据的缓存数组
iLen, i: integer;
begin
//判断参数的有效性
if not FileExists(aFile) or (comm = nil) then Exit;
//打开文件,准备读取
fs := TFileStream.Create(aFile, fmOpenRead);
with comm do try
try
//将固定长度的文件名写入发送头(简单的协议)
fn := ExtractFilename(aFile);
for i := 1 to LEN_FILENAME - Length(fn) do
fn := fn + ' ';
ss := Format(MARK_HEAD, [fn]);
WriteCommData(pchar(ss), Length(ss));
//延时
sleep(aDelay);
//循环读取文件数据并发送
repeat
try
iLen := fs.Read(buf, MAX_LENGTH);
if iLen > 0 then begin
WriteCommData(@buf, iLen);
sleep(aDelay);
end;
except
break;
end;
until iLen <= 0;
//发送数据结束标志(简单的协议)
WriteCommData(MARK_END, Length(MARK_END));
except
end;
finally
//保证文件的关闭
fs.Free;
end;
end;
接收端:
const //申明长度和简单的协议头、尾标识常量
MAX_LENGTH = 1024;
LEN_FILENAME = 255;
MARK_HEAD = '#MYFILE#';
MARK_END = '#END#';
var fs: TFileStream;
{
将文本串以流的方式写入文件
}
procedure writeStr(s: string; fs: TFileStream);
var
buf: array[1..MAX_LENGTH] of char; //数据缓存
i, j, iLen: integer;
begin
if fs = nil then Exit;
i := 1;
while i <= length(s) do begin
if Length(s) - i + 1 > MAX_LENGTH then
iLen := MAX_LENGTH
else
iLen := Length(s) - i + 1;
for j := i to i + iLen - 1 do
buf[j - i + 1] := s[j];
fs.Write(buf, iLen);
inc(i, iLen);
end;
end;
{
接收数据串到文件
}
procedure receiveData(ss: string);
var fn, s1: string;
begin
//判断文件头
if copy(ss, 1, Length(MARK_HEAD)) = MARK_HEAD then begin
//创建接收文件
if fs <> nil then fs.Free;
fn := trim(copy(ss, Length(MARK_HEAD) + 1, LEN_FILENAME));
fs := TFileStream.Create(fn, fmCreate);
//截取信息头和文件名以外的主体数据
s1 := copy(ss, Length(MARK_HEAD) + LEN_FILENAME + 1,
Length(ss) - Length(MARK_HEAD) - LEN_FILENAME);
//写入文件
writeStr(s1, fs);
end else
//判断结束标志
if pos(MARK_END, ss) <> 0 then begin
//截取结束标志以外的主体数据并写入文件
s1 := Copy(ss, 1, pos(MARK_END, ss) - 1);
writeStr(s1, fs);
//关闭文件
if fs <> nil then fs.Free;
fs := nil;
end else if fs <> nil then try
//将主体数据写入文件
writeStr(ss, fs);
except
end;
end;
{
Comm组件的数据接收事件
}
procedure TForm1.Comm1ReceiveData(Sender: TObject; Buffer: Pointer;
BufferLength: Word);
var i: integer;
s: array of char; //数据缓存
ss: string; //因为是文本信息,通过字符串方式处理
begin
//初始化缓存
setLength(s, BufferLength);
//接收数据到缓存
s := Buffer;
//生成数据串
ss := '';
for i := 0 to BufferLength - 1 do
ss := ss + s[i];
//接收到文件
receiveData(ss);
end;
后记:上面的代码只是给了个大体的思路,要真正的应用,还需要进一步的完善。