程序运行后,打开网络,监听数据存为了一个二进制文件,我们使用一个timer定时从文件中读取数据并更新,但是总是不断提示“Access Violation at address ……”,通过madexcept发现老是在下段程序中的“while i < n+1”的地方报错,先将程序附于下文://实时显示数据
procedure TDTUFrm.Timer1Timer(Sender: TObject);
var
x,n,rCnt,iRec,iDt:LongInt;
sdt,spn:string;
A:array of Char;
psize:Integer;
mypatrec:array of PatRec;
begin
//
x:=0;
iRec:=0;
psize:=0;
//
spn:=PathName;
n:=ReadBcdFile(spn,pchar(A));
//
rCnt:=n div RawPackages; //size of array
SetLength(mypatrec, rCnt+1); //获取数据信息
while x < n+1 do
begin
//--------------------------------STX
if A[x] = Char($02) then
begin
//-----------------------------ETX & CR
if ((A[x+51] = Char($03)) and (A[x+52] = Char($0D))) then
begin
//--------------------------DateTime
if (A[x+53] = Char($32))then
begin
psize:=PackageSizes;
//-----------------------Endpoint
mypatrec[iRec].PID:=Byte(A[x+1]);
//-----------------------Data
if A[x+2] = Char($01) then
begin
mypatrec[iRec].TmpQx:=DecodeTemp(A[x+36],A[x+37]);
mypatrec[iRec].TmpHb:=DecodeTemp(A[x+38],A[x+39]);
mypatrec[iRec].TmpSb:=DecodeTemp(A[x+40],A[x+41]);
mypatrec[iRec].TmpDt:=DecodeTemp(A[x+42],A[x+43]);
mypatrec[iRec].TmpXt:=DecodeTemp(A[x+44],A[x+45]);
mypatrec[iRec].TmpJd:=DecodeTemp(A[x+46],A[x+47]);
mypatrec[iRec].TmpHj:=DecodeTemp(A[x+48],A[x+49]);
for iDt:=0 to 18 do
mypatrec[iRec].RecDt:=mypatrec[iRec].RecDt+A[x+53+iDt];
Inc(iRec);
end
//-----------------------Order
else if A[x+2] = Char($02) then
begin
//保留 end;
end
//--------------------------Next STX
else if (A[x+RawPackages] = Char($02)) then
begin
psize:=RawPackages;
//考虑是否抛弃没有时间头的数据 end;
end
//$02字节并非起始位
else begin
psize:=1;
end;
end
else begin
psize:=1;
end;
//跳过该帧
x:=x+psize;
end; //数据记录
FillDatatoGrid(mypatrec,iRec);
end;//将文件数据读入
function TDTUFrm.ReadBcdFile(filename:string; var B:PChar):LongInt;
var
nsize:LongInt;
tmpfile:file;
begin
nsize:=0;
assignfile(tmpfile,filename);
reset(tmpfile,1);
try
nsize:=FileSize(tmpfile);
getmem(B,nsize+1);
BlockRead(tmpfile, B^, nsize);
B[nsize]:=#0;
finally
closefile(tmpfile);
Result:=nsize;
end;
end;非常感谢!
procedure TDTUFrm.Timer1Timer(Sender: TObject);
var
x,n,rCnt,iRec,iDt:LongInt;
sdt,spn:string;
A:array of Char;
psize:Integer;
mypatrec:array of PatRec;
begin
//
x:=0;
iRec:=0;
psize:=0;
//
spn:=PathName;
n:=ReadBcdFile(spn,pchar(A));
//
rCnt:=n div RawPackages; //size of array
SetLength(mypatrec, rCnt+1); //获取数据信息
while x < n+1 do
begin
//--------------------------------STX
if A[x] = Char($02) then
begin
//-----------------------------ETX & CR
if ((A[x+51] = Char($03)) and (A[x+52] = Char($0D))) then
begin
//--------------------------DateTime
if (A[x+53] = Char($32))then
begin
psize:=PackageSizes;
//-----------------------Endpoint
mypatrec[iRec].PID:=Byte(A[x+1]);
//-----------------------Data
if A[x+2] = Char($01) then
begin
mypatrec[iRec].TmpQx:=DecodeTemp(A[x+36],A[x+37]);
mypatrec[iRec].TmpHb:=DecodeTemp(A[x+38],A[x+39]);
mypatrec[iRec].TmpSb:=DecodeTemp(A[x+40],A[x+41]);
mypatrec[iRec].TmpDt:=DecodeTemp(A[x+42],A[x+43]);
mypatrec[iRec].TmpXt:=DecodeTemp(A[x+44],A[x+45]);
mypatrec[iRec].TmpJd:=DecodeTemp(A[x+46],A[x+47]);
mypatrec[iRec].TmpHj:=DecodeTemp(A[x+48],A[x+49]);
for iDt:=0 to 18 do
mypatrec[iRec].RecDt:=mypatrec[iRec].RecDt+A[x+53+iDt];
Inc(iRec);
end
//-----------------------Order
else if A[x+2] = Char($02) then
begin
//保留 end;
end
//--------------------------Next STX
else if (A[x+RawPackages] = Char($02)) then
begin
psize:=RawPackages;
//考虑是否抛弃没有时间头的数据 end;
end
//$02字节并非起始位
else begin
psize:=1;
end;
end
else begin
psize:=1;
end;
//跳过该帧
x:=x+psize;
end; //数据记录
FillDatatoGrid(mypatrec,iRec);
end;//将文件数据读入
function TDTUFrm.ReadBcdFile(filename:string; var B:PChar):LongInt;
var
nsize:LongInt;
tmpfile:file;
begin
nsize:=0;
assignfile(tmpfile,filename);
reset(tmpfile,1);
try
nsize:=FileSize(tmpfile);
getmem(B,nsize+1);
BlockRead(tmpfile, B^, nsize);
B[nsize]:=#0;
finally
closefile(tmpfile);
Result:=nsize;
end;
end;非常感谢!
前两天终于解决了,我直接把readBcdFile函数给改了,以免了使用太多动态数组变量,将数据传来传去,节省内存的开支。
最终使用Tfilestream将实时writefile的数据拷贝到一个临时文件,然后,通过position和seek移动指针读取数据,这样以提高使用指针的安全性。
代码就省了,回头要是谁感兴趣可以找我。