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