2011-08-09 18 views
9

私はこれがまったく些細なことだと思っていましたが、頭痛がありました。私は排他的アクセス権を持っていることを確認するためにファイルを開いて、特定の条件をテストしてから削除したいと思います。ファイルを正しく開くためにはどうすればよいですか?

今私は99%のアプローチを使用しています:

FileStream s = null; 
try { 
    s = new FileStream (
     path, 
     FileMode.Open, 
     FileAccess.ReadWrite, 
     FileShare.None); 
    // some stuff about the file is checked here 
    s.Dispose(); 
    // hope the file is not accessed by someone else... 
    File.Delete (path); 
    return true; 
} 
catch (IOException) { 
    if (s !=null) s.Dispose(); 
    return false; 
} 

をこの通常動作しますが、私は縁の条件を回避し、より良い方法があるはずと考えました。

削除チェックフラグ(既に設定されている削除フラグを使用して開いた後に発生する)がファイルを削除しないことを示す可能性があるため、DeleteOnCloseフラグを指定してファイルを開くと機能しません。

+0

これは役に立ちますが、codeplexの[トランザクションファイルマネージャ](http://transactionalfilemgr.codeplex.com/)プロジェクトを見てきましたか? – Oded

+3

ストリームを破棄する前にFileShare.Deleteでファイルを開き、File.Deleteを呼び出そうとしましたか? – Fox32

+0

実際には何が問題ですか? File.Deleteと同じ方法で、ファイルがすでにロックされている(または他の誰かによって削除されている)場合、最初のオープンはIOExceptionをスローできます。あなたは例外を捕まえて処理するので、どこが問題になるのですか? – Eddy

答えて

7

何か:

using (FileStream file = new FileStream(path, 
     FileMode.Open, 
     FileAccess.ReadWrite, 
     FileShare.Delete)) 
    { 
     // you can read the file here and check your stuff 
     File.Delete(path); 
    } 

PS: 'を使用して' キーワードを注意してください。これは、Dispose呼び出しを処理するので、よりクリーンなコードを持つことができます。

+0

コメントごとに、異なるアプリケーションがファイルにアクセスできるようにするのはどうだろうか? – mafu

+1

@mafutrct - FileShare.Deleteは、 "ファイルの後続の削除を許可する"ことを意味します。別のアプリでそれを削除することはできますが、書き込みも読み取りもできません。 –

+0

私の場合は、ファイルを削除しても問題にはなりません。むしろ、書かれたファイルを持っていれば、私はそれに対して別のQを置くつもりです。 – mafu

1

まず、 "using"ステートメントを真似していますが、間違ったやり方です。あなたは、tryとcatchで2回ではなく、finally節でファイルストリームを1回だけ破棄する必要があります。しかし、より良い使用を使用してください。

using (FileStream s = new FileStream()) 
{ 
} 

第二に、あなたは最高だオプションは、トランザクションNTFSは(ラッパーの1がNABU図書館で見つけることができます:https://dev.triflesoft.org/mercurial/nabu/)されて、あなたが必要とするので、もし、しかし、トランザクショナルNTFSは、NTFSおよびWindows Vista +に制限されていますFAT16/FAT32またはWindows XPの場合、これは方法ではありません。


また、他のプロセスによるアクセスを許可しないように開いたファイルの名前を変更/移動しようとすることができますが、これはNTFSすぎAFAIRに制限されています。


ファイルをすぐに削除する必要がない場合は、Setup APIのSetupQueueDelete関数を使用できます。このような

+0

処分開いているファイルを削除することはできないため、try内に必要です。 – mafu

+0

@mafutrctは、disposeの代わりにcloseを使用します。 –

+0

@ScottChamberlain:私はそれがどのように役立つか分かりません。 FileStreamの同じコードにマップを閉じたり取り除いたりしないでください。 – mafu

0

競合状態の可能性を完全に防ぐことはできません。変更されますチェックの間で、ファイルを削除した場合、プログラムが困っていることを考えると、そこに少なくとも2つの回避策は、私が見ることができます:

  • は、一時ファイル名を取得し、一時ファイルにファイルの名前を変更し、チェックを行います必要に応じて名前を戻します(ビジネスロジックに応じて新しい問題が発生する可能性があります)
  • ファイルのreadonly属性をチェックする前に設定することができます。
関連する問題