我正在尝试编写一段代码来获取文件列表,这些文件存在于文件夹结构中但不存在于另一个文件夹结构中。 换句话说,我只有在文件尚未归档时才归档文件。 这两个根文件夹是大约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的速度更快,但我真的希望使用框架。
答案 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());
}
}