Delphi при записи в сетевой ресурс с использованием TFilestream блокирует файл при потере сети
Я пытаюсь записать в сетевой ресурс (локальный), используя 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 ответа
Попробуйте закрыть файл с помощью API Network Share, а именно NetFileEnum
а также NetFileClose
функции. Смотрите также связанный вопрос
Я делаю что-то подобное, но не использую 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)
, - Если
bytesWritten
являются0
Вы знаете, дескриптор файла был потерян. Я положилtry ... finally
заблокировать весь мой код и выполнитьif fHandle > -1 then try FileClose(fHandle); except end;
так что это заставляет систему освобождать дескриптор файла, даже если файл больше не доступен. - Если
bytesWritten
было0
затем поспите несколько секунд и попробуйте снова.
Похоже, у меня была похожая проблема, как вы описали, пока я не добавил код:
if fHandle > -1 then
try
FileClose(fHandle);
except
end;
Я скопировал гигабайтные файлы на удаленный (медленный) сетевой ресурс, используя этот подход, и сетевой ресурс несколько раз терялся во время копирования. Я могу возобновить копирование, как только сетевой ресурс снова станет доступен. Вы должны быть в состоянии сделать что-то подобное с вашим файлом журнала...