5

TFilestream を使用してネットワーク共有 (ローカル) に書き込もうとしています。ネットワーク接続が中断されなければ、すべて正常に機能します。

ただし、ネットワーク ケーブルを抜いてから再接続すると、アクセス制限により、その後ファイル ストリームを開こうとすると失敗します。また、エクスプローラーでファイルを削除することさえできません! TFilestream がファイルをロックしているように見えますが、これを回避する唯一の方法は再起動することです。

私のアプリケーションでは、ファイルに書き込んでいる間ずっとファイルを開いたままにします (これは 1 秒ごとに書き込まれるログ ファイルです)。

失敗する私のコードは以下のとおりです。

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;

誰かにアドバイスがあれば、それはありがたいです。

4

2 に答える 2

7

Network Share API、つまりNetFileEnumandNetFileClose関数を使用してファイルを閉じてみてください。関連する質問も参照してください

于 2012-08-23T04:52:18.450 に答える
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;

このアプローチを使用してギガバイトのファイルをリモート(低速)ネットワーク共有にコピーしましたが、コピー中にネットワーク共有が数回失われました。ネットワーク共有が再び利用可能になり次第、コピーを再開できます。ログファイルで同様のことができるはずです...

于 2012-08-23T05:23:37.817 に答える