如何将c#中的一个文件集合与另一个文件集合进行比较?
我刚刚在学习C#(已经摆弄了大约2天了),我决定,为了学习,我将重建一个用VB6制作的旧应用程序,用于同步文件(通常通过网络) 当我在VB 6中编写代码时,其工作原理大致如下:如何将c#中的一个文件集合与另一个文件集合进行比较?,c#,fileinfo,directoryinfo,C#,Fileinfo,Directoryinfo,我刚刚在学习C#(已经摆弄了大约2天了),我决定,为了学习,我将重建一个用VB6制作的旧应用程序,用于同步文件(通常通过网络) 当我在VB 6中编写代码时,其工作原理大致如下: var sourceFiles = source.GetFiles(); var destFiles = dest.GetFiles(); var sourceFilesMissingInDestination = sourceFiles.Except(destFiles, new FileNameComparer()
var sourceFiles = source.GetFiles();
var destFiles = dest.GetFiles();
var sourceFilesMissingInDestination = sourceFiles.Except(destFiles, new FileNameComparer());
foreach (var file in sourceFilesMissingInDestination)
{
// Do whatever
}
脚本.FileSystemObject
- 如果没有,创建它
- 如果是,请检查源版本是否更新/更大,如果是,请覆盖其他版本
private bool syncFiles(string sourcePath, string destPath) {
DirectoryInfo source = new DirectoryInfo(sourcePath);
DirectoryInfo dest = new DirectoryInfo(destPath);
if (!source.Exists) {
LogLine("Source Folder Not Found!");
return false;
}
if (!dest.Exists) {
LogLine("Destination Folder Not Found!");
return false;
}
FileInfo[] sourceFiles = source.GetFiles();
FileInfo[] destFiles = dest.GetFiles();
foreach (FileInfo file in sourceFiles) {
// check exists on file
}
if (optRecursive.Checked) {
foreach (DirectoryInfo subDir in source.GetDirectories()) {
// create-if-not-exists destination subdirectory
syncFiles(sourcePath + subDir.Name, destPath + subDir.Name);
}
}
return true;
}
我读过一些示例,这些示例似乎提倡使用FileInfo或DirectoryInfo对象对“Exists”属性进行检查,但我特别想寻找一种方法来搜索现有的文件集合/列表,而不是对每个文件的文件系统进行实时检查,因为我将在网络上这样做,并且不断地返回数千个文件目录是很慢的
提前感谢。使用GetFiles()
方法只能获取确实存在的文件。它不构成不存在的随机文件。所以你所要做的就是检查它是否存在于其他列表中
这样做可能会奏效:
var sourceFiles = source.GetFiles();
var destFiles = dest.GetFiles();
foreach (var file in sourceFiles)
{
if(!destFiles.Any(x => x.Name == file.Name))
{
// Do whatever
}
}
注意:在调用GetFiles()
之后,您当然不能保证某些内容没有改变。例如,如果您稍后尝试复制某个文件,则该文件可能已被删除或重命名
也许用这种方法或类似的方法可以做得更好。例如,类似这样的事情:
var sourceFiles = source.GetFiles();
var destFiles = dest.GetFiles();
var sourceFilesMissingInDestination = sourceFiles.Except(destFiles, new FileNameComparer());
foreach (var file in sourceFilesMissingInDestination)
{
// Do whatever
}
其中FileNameComparer的实现方式如下:
public class FileNameComparer : IEqualityComparer<FileInfo>
{
public bool Equals(FileInfo x, FileInfo y)
{
return Equals(x.Name, y.Name);
}
public int GetHashCode(FileInfo obj)
{
return obj.Name.GetHashCode();
}
}
公共类FileNameComparer:IEqualityComparer
{
公共bool等于(FileInfo x,FileInfo y)
{
返回等于(x.Name,y.Name);
}
public int GetHashCode(FileInfo obj)
{
返回obj.Name.GetHashCode();
}
}
但未经测试:p一个小细节,而不是
sourcePath + subDir.Name
我会用
System.IO.Path.Combine(sourcePath, subDir.Name)
Path对文件名和文件夹名执行可靠的、独立于操作系统的操作
我还注意到,optRecursive.Checked
不知从哪里冒出来。作为一个良好的设计,将其作为一个参数:
bool syncFiles(string sourcePath, string destPath, bool checkRecursive)
由于您提到它可能用于大量文件,请注意.NET 4,它有一个IEnumerable替换项来替换GetFiles(),可以让您以流式方式处理此文件。对于子目录,也可以使用Path.Combine(sourcePath,subDir.Name)除了sourcePath+subDir.name之外,还可以看一下GetFileSystemInfos方法:至于您的注意:我理解,但这是一个风险,我会先加载获取文件列表的操作,这样我就不必对成千上万个文件进行单独的存在检查。非常感谢你的回答,我要去看看“Any”的语法!从DirectoryInfo获取所有目标文件的速度更快。不要在所有目标文件上都存在调用,但要检查文件打开调用是否成功,因为文件可以删除或重命名,就像斯维什解释的那样。@Martinho:这是个好主意。我正试图想出这样一个聪明的方法,但我的大脑却让我失望:p+1表示“既然你提到它可能用于大量文件,请注意.NET 4,它有一个IEnumerable代替GetFiles(),可以让你以流式方式处理它。”+1使用
Path.Combine
可以帮助您解决结尾斜杠存在而有时不存在的问题。这让生活很痛苦。我也喜欢使用Path.Combine
进行这种连接,但在这种情况下,为什么不直接使用subDir.FullName
?