【问题标题】:Fast FileSize Compare with LinqFast FileSize 与 Linq 的比较
【发布时间】:2012-05-02 09:09:07
【问题描述】:

我有两个文件目录,我想确保两者是相同的。因此,我创建了一个查询以将所有文件放入 FileInfo 数组中。我按文件名对所有文件进行了分组,现在想为每个组比较文件的“LastWriteAccess”和“长度”。

但是,老实说,就像我这样做,它的速度远远慢。任何想法我如何通过 Linq 比较组内的文件关于它们的长度,如果不同,让我做“某事”?

...

FileInfo[] fiArrOri5 = d5ori.GetFiles("*.*", System.IO.SearchOption.TopDirectoryOnly);
FileInfo[] fiArrNew5 = d5new.GetFiles("*.*", System.IO.SearchOption.TopDirectoryOnly);

FileInfo[] AllResults = new FileInfo[fiArrNew5.Length+fiArrOri5.Length];
fiArrNew5.CopyTo(AllResults, 0);
fiArrOri5.CopyTo(AllResults, fiArrNew5.Length);

var duplicateGroups = AllResults.GroupBy(file => file.Name);

        foreach (var group in duplicateGroups)
        {
            AnzahlElemente = group.Count();

            if (AnzahlElemente == 2)
            {
                if (group.ElementAt(0).Length != group.ElementAt(1).Length)
                {
                    // do sth
                }
            }

            ...
        }

编辑:

如果我只运行以下 sn-p,它会运行得非常快。 (~00:00:00:0005156)

Console.WriteLine(group.ElementAt(0).LastWriteTime);

如果我只运行以下 sn-p,它会运行得非常慢。 (~00:00:00:0750000)

Console.WriteLine(group.ElementAt(1).LastWriteTime);

知道为什么吗?

【问题讨论】:

  • 你想为每个不同的文件做点什么吗?或者只是两个目录之间有任何区别?
  • 缓慢的部分可能是从磁盘读取 FileInfo,对于每个文件...
  • Do Sth = 如果“原始”目录的文件具有较新的“LastWriteAccess”日期或与“镜像”目录的文件不同的“长度”,则将开始复制作业以替换镜像端的文件。慢速部分是 ElementAt(0) 与 ElementAt(1) 的“比较”。如果我删除 IF 部分,程序会在几秒钟内完成 400.000 个文件。如果我使用当前给定的 If compare 进行操作,则需要 6 个小时。这就是为什么我问是否有其他选择可以像我一样进行比较。
  • 我假设您不关心仅存在于一个或另一个目录中的文件?只出现在两者中的文件?
  • 对于这个例子,是的,我不关心它们。

标签: c# linq compare fileinfo


【解决方案1】:

我不确定这会更快 - 但我会这样做:

var folderPathOne = "FolderPath1";
var folderPathTwo = "FolderPath2";

//Get all the filenames from dir 1
var directoryOne = Directory
    .EnumerateFiles(folderPathOne, "*.*", SearchOption.TopDirectoryOnly)
    .Select(Path.GetFileName);

//Get all the filenames from dir 2
var directoryTwo = Directory
    .EnumerateFiles(folderPathTwo, "*.*", SearchOption.TopDirectoryOnly)
    .Select(Path.GetFileName);

//Get only the files that appear in both directories
var filesToCheck = directoryOne.Intersect(directoryTwo);

var differentFiles = filesToCheck.Where(f => new FileInfo(folderPathOne + f).Length != new FileInfo(folderPathTwo + f).Length);

foreach(var differentFile in differentFiles)
{
    //Do something
}

【讨论】:

  • “System.IO.Directory”不包含“EnumerateFiles”的定义。我也没有找到类似的东西。
  • 您使用的是什么版本的 .Net?我认为这可能只是 .Net 4.0...您可以使用 .GetFiles() 代替 - 但在这种情况下它会慢得多:(
  • 这种方法(或首先使用两组相交的类似方法)应该可以解决它。问题是 OrderBy 使用延迟执行,因此实际计算是在需要时执行的。结果 IEnumerable 中 IGrouping 项中的第一个元素相对于源 IEnumerable 是按顺序排列的,Linq 通常难以优化(我认为它在 O(n*log n) 中完成,但它可能碰巧是 O(n^2))...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多