原创 DLL编程经验(四)数据传输时候的文件读取问题

本文介绍使用Delphi编写的DLL通过文本文件进行跨语言通讯的方法。重点讲解了利用读写INI文件的形式来精确地读取和写入数据,并提供了具体的代码示例,包括如何处理异常、确保文件操作的安全性和一致性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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.仍然需要区分异步问题,譬如文件内容中增加内容说明或者特殊内容区分,区分不同文件名(含路径)等方式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值