删除不在数据表中的文件的最快方法

本文关键字:文件 方法 数据表 删除 | 更新日期: 2023-09-27 18:16:01

我需要在c#中编写代码,从数据表中选择文件名列表,并删除该列表中而不是的文件夹中的每个文件。

一种可能是按名称排序,然后循环遍历表结果,对于每个结果,循环遍历文件并删除它们,直到找到与当前结果匹配或字母顺序更大的文件,然后移动到下一个结果,而不重置当前文件索引。

我还没有尝试实际实现这一点,但在我看来,这将是一个O(n),因为每个列表将循环通过只一次(忽略排序两个列表部分)。我唯一不能确定的是,我是否可以100%确定文件系统和数据库引擎将以完全相同的方式排序(它们是否都认为"_"比"-"小之类的东西)。否则,上面的算法根本就不起作用。(顺便说一下,这是一个喷气发动机数据库。)

但是由于这可能不是一个不常见的问题,你们可能已经知道一个更好的解决方案。我试着在网上搜索,但什么也找不到。也许更有效的解决方案是将每个列表放入HashSet中并找出它们之间的差异。

删除不在数据表中的文件的最快方法

  1. 获取文件夹内容到folderFiles (IEnumerable<string>)
  2. 获取要保存在filesToKeep (IEnumerable<string>)中的文件
  3. 获取"not in list"文件列表
  4. 删除这些文件

代码示例:

IEnumerable<FileInfo> folderFiles = new List<FileInfo>(); // Fill me.
IEnumerable<string> filesToKeep = new List<string>();     // Fill me.
foreach (string fileToDelete in folderFiles.Select(fi => fi.FullName).Except(filesToKeep))
{
    File.Delete(fileToDelete);
}

这是我的建议。假设filesInDatabase包含数据库中的文件列表,pathOfDirectory包含要比较的文件所在目录的路径。

foreach (var fileToDelete in Directory.EnumerateFiles(pathOfDirectory).Where(item => !filesInDatabase.Contains(item))
{
    File.Delete(fileToDelete);
}
编辑:

需要using System.Linq;,因为它使用LINQ。

我认为散列是可行的方法,但实际上并不需要两个hashset。只需要一个HashSet来存储来自数据表的标准化文件名;另一个容器可以是任何集合数据类型。

首先,. net允许您定义可用于排序的区域性,但我对该机制并不十分熟悉,因此我将让Google给出有关该主题的指示。

其次,为了避免所有的文化质量,您可以使用一种不同的算法,其思想类似于基数排序(只是没有排序)——时间复杂度为O(n * length_longest_file_name)。文件名长度是有限的(据我所知,几乎没有文件系统允许文件名超过256),所以我假设n比文件名长度大得多,如果n小于最大文件名长度,只需使用O(n^2)方法并避免工作(迭代这么小的列表几乎是即时的)。注意:此方法不需要排序。

这个想法是创建一个符号数组,可以用作文件名字符(大约60-70个字符,如果这是一个区分大小写的搜索),以及另一个标志数组,其中第一个数组中的每个字符都有一个标志。现在,为来自DB的列表文件名中的每个字符创建一个循环(从1 -> length_longest_file_name)。在每次迭代(i)中,您遍历DB列表中每个文件名的第i个字符。你看到的每个char,你都把它的相关标志设为true。当设置了所有标志后,查看第二个列表并删除其名称的第i个字符未标记的每个文件。

的实现可能很复杂,而且当n较小时,两个数组的开销可能会使它变慢,但您可以对其进行优化以使其更好(例如,通过从两个列表中删除名称比当前i短的文件,而不遍历它们)。

希望能有所帮助

我有另一个可能更快的想法。

var filesToDelete = new List<string>(Directory.GetFiles(directoryPath));
foreach (var databaseFile in databaseFileList)
{
    filesToDelete.Remove(databaseFile);
}
foreach (var fileToDelete in filesToDelete)
{
    File.Delete(fileToDelete);
}

说明:首先获取目录中包含的所有文件。然后删除数据库中列表中的所有文件。最后从列表filesToDelete中删除所有剩余的文件。