Delphi编写的DLL与不少语言进行通讯不太好处理。譬如字符串、结构体。编写文本文件作为中间媒介则更加方便。
Delphi读取文本文件方法有多种,我比较喜欢用读取ini文件形式,这个形式能区分域、键、值精准定位到需要读取的数据点。
废话不多,直接来干货。
一、读:
unit IniFiles;//引入读写文件系统单元
function TClientSaveSetting.loadOCVFXManySetting(iniFileName: string): boolean;
var
myinifile: TInifile;
BattNum: string;
i, k,slotCount: Integer;
begin
result := false;
slotCount:=16;
try
try
k := FileOpen(iniFileName, fmOpenWrite or fmShareDenyNone); //独占方式读写
myinifile := TInifile.Create(iniFileName);
with myinifile do
begin
if not Assigned(myinifile) then Exit;
for i := 1 to slotCount do
begin
BattNum := 'BATT' + IntToStr(i);
dataPutEx.trayArr[i - 1].f_ocv := StrToFloat(ReadString(BattNum, 'f_ocv', '0'));
dataPutEx.trayArr[i - 1].f_ocr := StrToFloat(ReadString(BattNum, 'f_ocr', '0'));
dataPutEx.trayArr[i - 1].t_oct := StrToDateTime(FormatDateTime('YYYY-MM-DD HH:MM:SS', StrToDateTime(ReadString(BattNum, 't_oct', '1900-01-01 00:00:00'))));
dataPutEx.trayArr[i - 1].i_capGrd := StrToInt(ReadString(BattNum, 'i_capGrd', '0'));
dataPutEx.trayArr[i - 1].s_capComment := AnsiString(ReadString(BattNum, 's_capComment', ''));
end;
end;
except
on e:Exception do
begin
myinifile.WriteString('COMMON','RUN',e.Message);
Exit;
end;
end;
finally
myinifile.Free;
myinifile := nil;
FileClose(k); //独占方式读写 释放
if FileExists(iniFileName) then
DeleteFile(iniFileName);
result := True;
end;
end;
二、注意的点:
1)虽然只读,在读的过程中最好也给文件加锁。防止被修改,导致读取脏数据。
k := FileOpen(iniFileName, fmOpenWrite or fmShareDenyNone); //独占方式读写
2)读完需要记得取消锁
FileClose(k); //独占方式读写 释放
3)读取完成如果有必要删除原文件,防止下次读写时候引起内存错误。
if FileExists(iniFileName) then
DeleteFile(iniFileName);
4)读取的数据需要区分读取结果的类型,譬如bool类型需要检查是否读取到的是True/False还是数字1/0.
ReadString(BattNum, 'f_ocv', '0')//读取字符串、往往读取时间类型、布尔类型也会考虑用这个
ReadDateTime//读取时间
ReadBool//读取bool值
5)默认值
并非所有的读的内容都一定存在,一次一定要填写读取默认值,防止读取失败之后出现的一系列问题。
6)如果是同一接口频繁被调用的时候则需要考虑文件读写异步引发读取脏数据。处理方法如下:
a.传入文件用不同名称区分,防止重复读取
b.传入进来之后做文件校验,防止已被更改
c.传入进来之后做拷贝再读写,减少占用时间来达到目的
三、 写:
直接上代码:
{
created by:JustinYang 20171009
function:将东磁托盘条码相关数据保存到文本,万克分选机调用
}
function TClientSaveSetting.saveSettingDC2(iniFileName: string;trayID:string;trayRFID:Int64; var trayArrCust: TTrayArrayExDC2):Boolean;
var
myinifile: TInifile;
i, k: Integer;
BattNum: string;
sysDir,fileName: string;
begin
result:=False;
//20170419 东磁数据异常 保留一份
sysDir:= ExtractFilePath(ParamStr(0)) + 'log\' + formatdatetime('yyyyymmdd', Now()) + '\' ;
if not directoryexists(ExtractFilePath(sysdir)) then
ForceDirectories(ExtractFilePath(sysdir));
if trayRFID > 0 then
fileName := sysDir + IntToStr(trayRFID) + '.set'
else
fileName := sysDir + trayID + '.set';
if FileExists(fileName) then DeleteFile(fileName);
try
myinifile := TInifile.Create(fileName);
k := FileOpen(fileName, fmOpenWrite or fmShareDenyNone); //独占方式读写
with myinifile do
begin
try
if not Assigned(myinifile) then Exit;
WriteInteger(trayID+'_'+IntToStr(trayRFID), 'BattNum', trayArrCust.Count);
for i := 1 to trayArrCust.Count do
begin
BattNum := 'BATT' + IntToStr(trayArrCust.Items[i - 1].i_trayNum);
WriteString(BattNum, 'battID', trayArrCust.Items[i - 1].s_battID);
//OCV数据
WriteString(BattNum, 'f_OCV1', floatToStr(trayArrCust.Items[i - 1].f_OCV1));
WriteString(BattNum, 't_OCT1', DateTimeToStr(trayArrCust.Items[i - 1].t_OCT1));
WriteString(BattNum, 'f_OCV2', floatToStr(trayArrCust.Items[i - 1].f_OCV2));
WriteString(BattNum, 't_OCT2', DateTimeToStr(trayArrCust.Items[i - 1].t_OCT2));
WriteString(BattNum, 'f_OCV3', floatToStr(trayArrCust.Items[i - 1].f_OCV3));
WriteString(BattNum, 't_OCT3', DateTimeToStr(trayArrCust.Items[i - 1].t_OCT3));
WriteString(BattNum, 'f_OCV5', floatToStr(trayArrCust.Items[i - 1].f_OCV5));
WriteString(BattNum, 't_OCT5', DateTimeToStr(trayArrCust.Items[i - 1].t_OCT5));
//分容数据
WriteString(BattNum, 'f_Cap_DCT', floatToStr(trayArrCust.Items[i - 1].f_Cap_DCT));
end;
result:=True;
except
on e:Exception do
begin
WriteString('COMMON','RUN',e.Message);
result:=False;
end;
end;
end;
finally
if result=True then
myinifile.WriteString('COMMON','result','True')
else myinifile.WriteString('COMMON','result','False');
FileClose(k); //独占方式读写 释放
myinifile.free;
end;
end;
a.写需要注意没有值的填写默认值
b.文件或者目录不存在的先强制创建目录、创建文件,防止因找不到文件夹或者文件名出错
if not directoryexists(ExtractFilePath(sysdir)) then
ForceDirectories(ExtractFilePath(sysdir));
c.仍然需要区分异步问题,譬如文件内容中增加内容说明或者特殊内容区分,区分不同文件名(含路径)等方式。