2012-08-23 9 views
5

TFilestreamを使用してネットワーク共有(ローカル)に書き込もうとしています。ネットワーク接続がインターラプトされないと、すべて正常に動作します。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; 

場合、それをいただければ幸いです。

+0

これは本当にTFileStreamの問題ですか?その場合は、CreateFileのようなものを使用してください。 –

答えて

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)です。
  • 0の場合、ファイルハンドルが失われたことがわかります。すべてのコードにtry ... finallyブロックを置き、if fHandle > -1 then try FileClose(fHandle); except end;を実行して、ファイルにアクセスできない場合でもシステムがファイルハンドルを解放するようにします。
  • bytesWritten0の場合は、数秒間スリープしてからもう一度お試しください。

    if fHandle > -1 then 
        try 
        FileClose(fHandle); 
        except 
        end; 
    
    私はこのアプローチを使用してリモート(遅い)ネットワーク共有にギガバイトのファイルをコピーした

    、およびネットワーク:私は、コードを追加するまで、あなたが説明するように、私は同様の問題があったよう

に思えますコピー中にシェアが数回失われた。ネットワーク共有が再び利用可能になるとすぐにコピーを再開することができます。あなたはあなたのログファイルと同様の何かをすることができるはずです...

+4

これは答えではありません。ネットワークが戻ってこない場合はどうすればいいですか?今あなたはプログラムがビジーなループに掛かっています。 FWIWは旧式のファイルAPIを使用する必要はなく、そのコードはTFileStreamで簡単に書き込むことができます。 –

+0

これをパターン化したコードでは、最大再試行回数があるため、ビジーなループではロックされません。それは簡単に追加できます。私は、TFileStreamと旧式のファイルAPIが別の方法で処理したかどうか、それが問題の一部であるかどうかはわかりませんでした。私はそれがファイルAPIで動作することを知っているので、私はSimonがそのオプションの仕組みを知りたがっていました... –

関連する問題