2

ファイルへのパスのリストを含む DB があります。フォルダーをクリーンアップするルーチンを作成し、db レコードがない場合はディレクトリ内のファイルを削除します (一時的な ajax ファイルのアップロード、ユーザーがフォームに入力しない場合など)。

私はこのようなことを考えています:

var dbFiles = db.allPaths();
var allFiles = Directory.EnumerateFiles(path);

foreach (var f in allFiles) {
  if (!dbFiles.Contains(f) {
    File.Delete(f);
  }
}

私を待っている「落とし穴」はありますか?ルーチンは、最初は週に 1 回実行するように設定されますが、一時ファイルが問題になると、より頻繁に実行されます。ユーザーがほとんどいない時間帯に実行されるため、パフォーマンスは重要ですが、最優先事項ではありません。

アップデート

うわー、たくさんの素晴らしい答え。このコードは、「共有」に値するものに変わりつつあります。;D 上記の私のコードは、単純で簡単なプレースホルダー ビットでした... しかし、しっかりしたコードに変換されます。ありがとうございました!

4

4 に答える 4

8

問題ないように見えますが、もっと簡単にすることができます:

foreach (var file in allFiles.Except(dbFiles))
{
    File.Delete(file);
}

ただし、パスがまったく同じ形式であることを確認する必要があります。一方のリストに相対ファイルがあり、もう一方のリストに絶対ファイルがある場合、または一方が「/」を使用し、もう一方が「\」を使用している場合、予期しないものを削除することになります。

最初にファイルを明示的に正規化するのが理想的ですが、.NET で正規のファイル名を取得する良い方法がわかりません...

編集:正規化Path.GetFullPathしないことに注意してください。スラッシュを修正して絶対にしますが、大文字と小文字を区別しません: "c:/users" は "c:\users" になりますが、"c:/Users" は "c:\Users" になります。

これは、への呼び出しで文字列比較子を使用することで修正できますExcept

var dbFiles = db.AllPaths().Select(Path.GetFullPath));
var allFiles = Directory.EnumerateFiles(path).Select(Path.GetFullPath));

foreach (var file in allFiles.Except(dbFiles, StringComparer.OrdinalIgnoreCase))
{
    File.Delete(file);
}

これは大文字と小文字を区別しませんが、「通常の」方法です。大文字と小文字の区別に関して、Windows ファイル システムが実際に何をしているのかはわかりません。

于 2010-06-22T06:17:21.903 に答える
3

は、私にはよく見えますよ; ただし、VBだけで、C#内でファイルを削除したことはありません。ただし、ファイルを削除できない場合 (読み取り専用、現在使用中、存在しないなど) の場合は、Try/Catch ループにスローすることをお勧めします。例外がスローされます。

編集:パスはどのように保存されますか? C# では、"\" IIRC を使用する代わりにパス "//" をエスケープする必要があることに注意してください。

編集 2: 最後の編集をスクラッチします。

于 2010-06-22T06:11:04.197 に答える
1

精神的には問題ないと思いますが、次のようになります。

List<string> dbFiles = db.allPaths();
string[] allFiles = Directory.GetFiles(path);

foreach (string f in allFiles)
    if (!dbFiles.Contains(f))
        File.Delete(f);
于 2010-06-22T06:18:20.980 に答える
1

すべての提案を 1 つにまとめるには:

// canonicalize paths
var dbFiles = db.allPaths().Select(Path.GetFullPath);
var allFiles = Directory.EnumerateFiles(Path.GetFullPath(path))

foreach (var file in allFiles.Except(dbFiles, StringComparer.OrdinalIgnoreCase))
{
    try {
        File.Delete(file);
    } catch (IOException) {
        // handle exception here
    }
}
于 2010-06-22T06:36:21.883 に答える