Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi使用TFilestream写入网络共享时会在网络丢失时锁定文件_Delphi_Logging_Filestream_File Locking - Fatal编程技术网

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

Delphi使用TFilestream写入网络共享时会在网络丢失时锁定文件,delphi,logging,filestream,file-locking,Delphi,Logging,Filestream,File Locking,我正在尝试使用TFilestream写入网络共享(本地)。如果网络连接没有被中断,一切正常 但是,如果我拔出网络电缆,然后重新连接,由于访问限制,随后打开filestream的尝试将失败。我甚至不能删除资源管理器中的文件!TFilestream似乎锁定了文件,解决这个问题的唯一方法是重新启动 在我的应用程序中,我在写入文件的整个过程中都保持文件打开(它是一个每秒写入一次的日志文件) 我失败的代码如下: procedure TFileLogger.SetLogFilename(const Valu

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

但是,如果我拔出网络电缆,然后重新连接,由于访问限制,随后打开filestream的尝试将失败。我甚至不能删除资源管理器中的文件!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;
procedure TFileLogger.SetLogFilename(常量值:字符串);
var行:字符串;
创建:布尔;
开始
如果目录不存在(ExtractFilePath(Value)),则//如果目录不存在,则创建该目录
开始
尝试
ForceDirectories(ExtractFilePath(Value));
除了
错误消息(值)//无法访问目录,因此标记错误
出口
结束;
结束;
如果值为FLogFilename,则//创建或打开现有
开始
创建:=假;
如果已分配(FStream),则
FreeandNil(FStream);
如果文件不存在(值),则//创建文件并写入头
开始
//现在创建一个新文件
尝试
FStream:=TFileStream.Create(值,fmCreate);
已创建:=真;
最后
FreeAndNil(FStream);
结束;
如果未创建,则//创建文件时出现问题
开始
错误消息(值);
出口
结束;
FLogFilename:=值;
//现在打开文件进行写入
FStream:=TFileStream.Create(FLogFilename、fmOpenWrite或fmharedenywrite);
尝试
行:=FHeader+#13#10;
FStream.Seek(0,索夫罗门);
写入(行[1],长度(行));
FSuppress:=假;
除了
错误消息(值);
结束;
结束或开始//打开它
FLogFilename:=值;
//现在打开文件进行写入
FStream:=TFileStream.Create(FLogFilename、fmOpenWrite或fmharedenywrite)//如果网络丢失,然后重新连接,此线路将失败
结束;
结束;
结束;

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

尝试使用
NetFileEnum
NetFileClose
功能关闭您的文件。另请参见

我做了类似的事情,但不使用
TFileStream
。我使用
SysUtils
中的文件方法。以下是我根据您的情况所做的基本工作:

// variables used in pseudo-code below
var
  fHandle, bytesWriten: Integer;
  Value: string;
  • 使用
    fHandle:=FileOpen('filename',fmOpenReadWrite或…)打开输出文件
  • 验证是否为
    fHandle>-1
    ,如果不是,则休眠并循环
  • 写入输出
    bytesWrite:=FileWrite(fHandle,Value,Length(Value))
  • 检查
    字节写入
    ,它们应该
    =长度(值)
  • 如果写入的
    字节
    0
    ,则您知道文件句柄已丢失。我放了一个
    试试。。。最后
    阻塞所有我的代码并执行
    如果fHandle>-1,则尝试FileClose(fHandle);除了结束
    以强制系统释放文件句柄,即使文件不再可访问
  • 如果写入的
    字节数为
    0
    ,请睡眠几秒钟,然后重试
在添加代码之前,我似乎遇到了与您描述的类似的问题:

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

我已经使用这种方法将千兆字节的文件复制到远程(慢速)网络共享,并且在复制过程中,网络共享已经丢失了好几次。一旦网络共享重新可用,我就可以恢复副本。您应该能够对日志文件执行类似的操作…

这不是答案。如果网络再也没有回来呢?现在,您的程序挂起在一个繁忙的循环中。FWIW不需要使用老式的文件API,使用TFileStream可以轻松编写代码;这很容易添加。我不知道TFileStream和老式的文件API是否以不同的方式处理问题,也不知道这是否是问题的一部分。因为我知道它与文件API一起工作,所以我想让Simon知道该选项是如何工作的……这真的是TFileStream的问题吗?如果是这样的话,那么就使用其他东西,比如CreateFile。