获取文件列表的性能问题(VBA和C#.NET 4.0)

时间:2015-03-23 11:41:59

标签: c# vba getfiles

我正在尝试编写一段代码来获取文件列表,这些文件存在于文件夹结构中但不存在于另一个文件夹结构中。 换句话说,我只有在文件尚未归档时才归档文件。 这两个根文件夹是大约1000个用户可能使用的网络文件夹。

在我的第一次尝试中,我使用了Excel工作簿中的VBA。 我使用shell获取列表,然后使用“Dir”命令检查它们在另一个文件夹中的存在。

这是我的代码的一部分:

更新 - 这是我的代码:

Dim arr
Dim i As Integer
Dim sFolder As String
Dim sYear As String
Dim sDecade As String
Dim sGFolder As String
Dim sDestXLF As String

sFolder = "T:\FirstRootFolder\"

arr = Filter(Split(CreateObject("wscript.shell").exec("cmd /c Dir ""T:\FirstRootFolder\xx*"" /b /ad /on").StdOut.ReadAll, vbCrLf), ".")

For i = 1 To UBound(arr)
  If Dir(sFolder & arr(i) & "\*.xlf") <> "" Then
    sYear = Right(arr(i), 2)
    sDecade = Mid(arr(i), 3, 2)
    sGFolder = "G:\SecondFolderRoot\" & sYear & "\xx\xx" & sDecade & "\"
    sDestXLF = sGFolder & arr(i) & ".it.xlf"
    If Dir(sDestXLF) = vbNullString Then
      ListBox1.AddItem arr(i)
    End If
  End If
Next i

它工作正常,大约需要6秒钟才能完成。

现在,我正在学习框架和C#,所以我试着在不打开Excel的情况下做同样的事情。 我尝试了不同的解决方案,但使用shell命令(GetFiles,FileExists,ecc),我最终得到了这个:

string FirstFolderRoot, SecondFolderRoot;
lboLista.DataSource = null;

FirstFolderRoot = @"T:\FirstRootFolder\";
SecondFolderRoot = @"G:\SecondFolderRoot\";

var foundFilesFirst = Directory.EnumerateFiles(FirstFolderRoot, "*.xlf", SearchOption.AllDirectories)
                     .Where(s => s.Contains("xx"))
                     .Select(m => Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(m))).ToArray();
var foundFilesSecond = Directory.EnumerateFiles(SecondFolderRoot, "*.xlf", SearchOption.AllDirectories)
                     .Select(m => Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(m))).ToArray();

var foundFiles = foundFilesFirst.Except(foundFilesSecond);
lboLista.DataSource = foundFiles.ToList();

它也可以正常工作,但需要大约1分半才能完成,大部分时间用于填充这两个系列。

有没有办法让VBA具有可比性? 真的shell命令是否比框架更快,或者我没有以正确的方式使用它?

我读到使用winapi的速度更快,但我真的希望使用框架。

1 个答案:

答案 0 :(得分:0)

请查看此处的示例:msdn link,以获取C#.NET中目录和文件比较的示例。它使用IEqualityComparer()SequenceEqual()

瓶颈将是运行两个GetFiles()命令所花费的时间。如果它们是不同的网络驱动器,则可以在单独的线程中运行,以提高性能。

为清楚起见,这是一个略有修改的摘录:

// This implementation defines a very simple comparison 
// between two FileInfo objects. It only compares the name 
// of the files being compared and their length in bytes. 
class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{
    public FileCompare() { }

    public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
    {
        return (f1.Name == f2.Name &&
                f1.Length == f2.Length);
    }

    // Return a hash that reflects the comparison criteria. According to the  
    // rules for IEqualityComparer<T>, if Equals is true, then the hash codes must 
    // also be equal. Because equality as defined here is a simple value equality, not 
    // reference identity, it is possible that two or more objects will produce the same 
    // hash code. 
    public int GetHashCode(System.IO.FileInfo fi)
    {
        string s = String.Format("{0}{1}", fi.Name, fi.Length);
        return s.GetHashCode();
    }
}


class CompareDirs
{

    static void Main(string[] args)
    {
        // Create two identical or different temporary folders  
        // on a local drive and change these file paths. 
        string pathA = @"C:\TestDir";
        string pathB = @"C:\TestDir2";

        System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
        System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);

        // Take a snapshot of the file system.
        IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
        IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.*", System.IO.SearchOption.AllDirectories);

        //A custom file comparer defined below
        //Use Except to retrieve files from list2 not in list1
        var uniqueFiles = list1.Except(list2, new FileCompare());
   }

}