当网络丢失时,Delphi使用TFilestream写入网络共享会锁定文件

时间:2012-08-23 03:45:25

标签: delphi logging filestream file-locking

我尝试使用TFilestream写入网络共享(本地)。如果没有中断网络连接,一切正常。

但是,如果我拉动网络电缆然后重新连接,则后续尝试打开文件流会因访问限制而失败。我甚至无法删除资源管理器中的文件!看来TFilestream会锁定文件,解决这个问题的唯一方法就是重启。

在我的应用程序中,我在写入文件的整个过程中保持文件打开(这是每秒写一次的日志文件)。

我失败的代码如下:

procedure TFileLogger.SetLogFilename(const Value: String);
var line : String;
Created : Boolean;
begin
  if not DirectoryExists(ExtractFilePath(Value)) then //create the dir if it doesnt exist
  begin
       try
         ForceDirectories(ExtractFilePath(Value));
       except
         ErrorMessage(Value); //dont have access to the dir so flag an error
         Exit;
       end;
  end;
  if Value <> FLogFilename then //Either create or open existing
  begin
      Created := False;          
      if Assigned(FStream) then
         FreeandNil(FStream);
      if not FileExists(Value) then   //create the file and write header
      begin
           //now create a new file
           try
              FStream := TFileStream.Create(Value,fmCreate);
              Created := True;
           finally
             FreeAndNil(FStream);
           end;
           if not Created then //an issue with creating the file
           begin
                ErrorMessage(Value);
                Exit;
           end;
           FLogFilename := Value;
           //now open file for writing
           FStream := TFileStream.Create(FLogFilename,fmOpenWrite or fmShareDenyWrite);
           try
              line := FHeader + #13#10;
              FStream.Seek(0,soFromEnd);
              FStream.Write(Line[1], length(Line));
              FSuppress := False;
           except
              ErrorMessage(Value);  
           end;
      end else begin //just open it
           FLogFilename := Value;
           //now open file for writing
           FStream := TFileStream.Create(FLogFilename,fmOpenWrite or fmShareDenyWrite); //This line fails if the network is lost and then reconnected
      end;
  end;
end;

如果有人有任何建议,我们将不胜感激。

2 个答案:

答案 0 :(得分:7)

尝试使用Network Share API关闭您的文件,即NetFileEnumNetFileClose个功能。另请参阅a related question

答案 1 :(得分:0)

我做了类似的事情,但没有使用TFileStream。我使用SysUtils中的文件方法。这基本上就是我做的,适合你的情况:

// variables used in pseudo-code below
var
  fHandle, bytesWriten: Integer;
  Value: string;
  • 使用fHandle := FileOpen('filename', fmOpenReadWrite or ...)打开输出文件。
  • 验证是fHandle > -1,睡眠和循环,如果它不是
  • 写出输出bytesWritten := FileWrite(fHandle, Value, Length(Value));
  • 检查bytesWritten,他们应该= Length(Value)
  • 如果bytesWritten0,则表示文件句柄已丢失。我在我的所有代码周围放置了一个try ... finally块并执行if fHandle > -1 then try FileClose(fHandle); except end;,这样即使文件不再可访问,它也会强制系统释放文件句柄。
  • 如果bytesWritten0,请暂停几秒钟再试一次。

在我添加代码之前,我似乎遇到了类似的问题:

if fHandle > -1 then
  try
    FileClose(fHandle);
  except
  end;

我已使用此方法将千兆字节文件复制到远程(慢速)网络共享,并且在复制期间网络共享已丢失多次。一旦网络共享再次可用,我就可以恢复副本。您应该可以使用与日志文件类似的内容...