需求:在向指定文件写数据时,同时能够打开文件并读取数据,并不出现文件被另一个程序占用的错误。
目前是用Tstringlist来存储串口发出来的数据,因为要求存储文件中只存最新接收的数据,所以在接收新的数据时要把以前的删掉,用Tstringlist可以用clear来清空列表,但用Tstringlist存数据时,如果打开读数据的话会出现共享错误。用什么方式来存,在打开时可以不出现文件被占用的错误先谢谢了。。

解决方案 »

  1.   

    先分析一下产生错误的原因>>但用Tstringlist存数据时,如果打开读数据的话会出现共享错误。1.假设LZ是用Stringlist.SaveToFile(FileName);来保存Stringlist中的数据到文件中时从VCL中,看看实现上Stringlist.SaveToFile是怎么作的在classes.pas单元中procedure TStrings.SaveToFile(const FileName: string);
    var
      Stream: TStream;
    begin
      Stream := TFileStream.Create(FileName, fmCreate);  //以fmCreate方式创建一个流
      try
        SaveToStream(Stream);//然后将StringList中的内容,保存到流中,即保存就文件中
      finally
        Stream.Free;
      end;
    end;再看看TFileStream.Create(FileName, fmCreate); 是如何处理的 
    TFileStream的构造函数
    constructor TFileStream.Create(const FileName: string; Mode: Word);
    begin
    {$IFDEF MSWINDOWS}
      Create(Filename, Mode, 0);//调用另一个重载构造函数
    {$ELSE}//重载的构造函数Create
    constructor TFileStream.Create(const FileName: string; Mode: Word; Rights: Cardinal);
    begin
      if Mode = fmCreate then
      begin
        inherited Create(FileCreate(FileName, Rights)); //这里调用FileCreate函数创建文件    if FHandle < 0 then
          raise EFCreateError.CreateResFmt(@SFCreateErrorEx, [ExpandFileName(FileName), SysErrorMessage(GetLastError)]); //如果失败,就抛出异常,如LZ程序中的错误提示
      end再看看SysUntil.pas单元中,FileCreate这个函数如何处理function FileCreate(const FileName: string): Integer;
    {$IFDEF MSWINDOWS}
    begin
      Result := Integer(CreateFile(PChar(FileName), GENERIC_READ or GENERIC_WRITE,
        0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
    end;从上看出是调用windows的api CreateFile来创建文件,而且是以CREATE_ALWAYS这个标志来创建文件的从MSDN中可查到,CREATE_ALWAYS这个标志,表示,
    Creates a new file. If the file exists, the function overwrites the file and clears the existing attributes.所以,如果在文件已经被打开的情况下,使用CREATE_ALWAYS的方式来保存到这个文件,就会出现LZ程序中的错误提示
      

  2.   

    从上边的分析来看,可以容易地找出问题的原因。也说明了一点Delphi的VCL,有部分是对windows api的封装,对windows sdk越熟悉,对DELPHI理解也会更透彻。为避免出现这样的错误提示,解决办法有1.简单点,在调用SaveToFile时,关闭 在程序中别的地方打开这个文件的句柄。2.作好一些的话,可以将 对这些数据的接收、处理、更新保存到文件,从文件中读取内容等待相关的功能操作 封装成一个类来实现。  在类中处理好相关的逻辑,应该是很安全的。
      

  3.   

    do2008(aiGooo·闲来吹吹牛,不亦乐乎) 
    classes.pas,SysUntil.pas这些单元文件是在什么地方放啊?
    非常感谢你这么透彻的分析
      

  4.   

    do2008(aiGooo·闲来吹吹牛,不亦乐乎)
    分已送出,请查收。。