这个删除不在数组中的所有文件的 C# 例程看起来没问题吗?

发布于 2024-09-06 16:44:28 字数 501 浏览 4 评论 0原文

我有一个包含文件路径列表的数据库。我想构建一个例程来清理文件夹,如果没有数据库记录,则删除目录中的文件(用于临时ajax文件上传,在用户未完成表单的情况下,等等...)。

我在想这样的事情:

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

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

有什么“陷阱”在等着我吗?该例程最初将设置为每周运行一次,如果临时文件出现问题,则运行频率会更高。它将在几乎没有用户的情况下运行,因此性能虽然很重要,但并不是最重要的。

更新

哇,有很多很棒的答案。这段代码正在变成值得“分享”的东西。 ;D 我上面的代码只是一个简单、快速的占位符位...但它已转换为可靠的代码。谢谢你!

I have a DB that contains a list of paths to files. I want to build a routine to cleanup the folders, removing files in the directories if there is not a db record for it (for temp ajax file uploads, in cases where the user doesn't complete the form, etc...).

I'm thinking something like this:

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

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

Any "Gotchas" waiting for me? The routine will be set to run once a week at first, more often if temp files become a problem. It will be run during a time when there are nearly no users on, so performance - while important - is not paramount.

UPDATE

Wow, lots of great answers. This bit of code is turning into something "share" worthy. ;D My code above was just a simple, quick placeholder bit... but it's transformed into solid code. Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

静赏你的温柔 2024-09-13 16:44:28

看起来不错,但您可以使其更简单:

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 文件系统在区分大小写方面真正做什么。

Looks okay, but you can make it simpler:

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

You've got to make sure that the paths are in exactly the same format though. If one list has relative files and the other has absolute files, or if one uses "/" and the other uses "\" you'll end up deleting things you don't expect to.

Ideally you'd canonicalise the files explicitly first, but I can't see a nice way of getting a canonical file name in .NET...

EDIT: Note that Path.GetFullPath does not canonicalize. It fixes slashes and makes it absolute, but it doesn't address case: "c:/users" becomes "c:\users", but "c:/Users" becomes "c:\Users".

This could be fixed by using a string comparer in the call to 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);
}

Now that's ignoring case - but in an "ordinal" manner. I don't know what the Windows file system really does in terms of its case sensitivity.

柳若烟 2024-09-13 16:44:28

我觉得不错;但是我从来没有在 C# 中删除过文件,只是在 VB 中删除过文件。
但是,您可能希望将其放入 Try/Catch 循环中,就好像该文件无法删除(只读、当前正在使用、不再存在等)一样,它将引发异常。

编辑:路径如何存储?请记住,在 C# 中,您需要转义路径“//”而不是使用“\”IIRC。

编辑2:把最后的编辑内容去掉,哈哈。

Looks good to me; however I've never deleted files within C#, just VB.
However, you might want to throw that into a Try/Catch loop, as if the file isn't able to be deleted (read-only, currently in use, no longer exists, etc.), it will throw an exception.

EDIT: How are the paths stored? Remember, in C# you need to escape out paths "//" instead of using "\" IIRC.

EDIT 2: Scratch that last edit out lol.

不即不离 2024-09-13 16:44:28

将所有建议合并为一个:

// 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
    }
}

To combine all the suggestions into one:

// 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
    }
}
乱了心跳 2024-09-13 16:44:28

我认为它在精神上是好的,尽管它会更接近:

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

foreach (string f in allFiles)
    if (!dbFiles.Contains(f))
        File.Delete(f);

I think it's alright in spirit, though it would be closer to:

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

foreach (string f in allFiles)
    if (!dbFiles.Contains(f))
        File.Delete(f);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文