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;

Я скопировал гигабайтные файлы на удаленный (медленный) сетевой ресурс, используя этот подход, и сетевой ресурс несколько раз терялся во время копирования. Я могу возобновить копирование, как только сетевой ресурс снова станет доступен. Вы должны быть в состоянии сделать что-то подобное с вашим файлом журнала...

Другие вопросы по тегам