我正在尝试扩展文件比较器,以从要比较的文件路径中减去根路径。问题出在GetHashCode()
方法中,因为我有两个不同的根路径(root_a和root_b)。如何正确实现将相应的根拍分配给正确的文件?
class FileCompare : System.Collections.Generic.IEqualityComparer<System.IO.FileInfo>
{
string m_root_a;
string m_root_b;
public FileCompare() { }
public FileCompare(string root_a, string root_b)
{
m_root_a = root_a;
m_root_b = root_b;
}
public bool Equals(System.IO.FileInfo f1, System.IO.FileInfo f2)
{
return (f1.FullName.Substring(m_root_a.Length) ==
f2.FullName.Substring(m_root_b.Length) &&
f1.Length == f2.Length);
}
public int GetHashCode(System.IO.FileInfo fi)
{
string s = $"{fi.FullName.Substring(m_root_a.Length)}{fi.Length}";
return s.GetHashCode();
}
}
测试比较器的代码:
System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo("C:\\Dir Compare Tmp\\dir1\\");
System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo("C:\\Dir Compare Tmp\\dir2\\");
IEnumerable<System.IO.FileInfo> list1 = dir1.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
IEnumerable<System.IO.FileInfo> list2 = dir2.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
FileCompare myFileCompare = new FileCompare("C:\\Dir Compare Tmp\\dir1\\",
"C:\\Dir Compare Tmp\\dir2\\");
bool areIdentical = list1.SequenceEqual(list2, myFileCompare);
List<string> commonFilesList = new List<string>();
List<string> files1OnlyList = new List<string>();
List<string> files2OnlyList = new List<string>();
var queryCommonFiles = list1.Intersect(list2, myFileCompare);
var queryList1Only = (from file in list1 select file).Except(list2, myFileCompare);
var queryList2Only = (from file in list2 select file).Except(list1, myFileCompare);
foreach (var v in queryCommonFiles)
commonFilesList.Add(v.FullName);
foreach (var v in queryList1Only)
files1OnlyList.Add(v.FullName);
foreach (var v in queryList2Only)
files2OnlyList.Add(v.FullName);
[更新:不幸的是,当我的根路径长度不同时,代码无法正常工作。第二路径C:\\Dir Compare Tmp\\dir2 - Copy\\
。我没有在commonFilesList中得到任何文件(从答案中使用GetHashCode实现; Equals函数失败)。有什么解决方案,还是应该使用其他方法比较文件?这将用于比较大量文件,因此代码延迟很重要。
由于您的比较器已经存储了根路径,并且只希望将那些路径中的文件传递给GetHashCode方法,所以我希望以下实现能够完成您想要实现的目标。
public int GetHashCode(System.IO.FileInfo fi)
{
if(fi.FullName.StartsWith(m_root_a))
return fi.FullName.SubString(m_root_a.Length).GetHashCode();
else if(fi.FullName.StartsWith(m_root_b))
return fi.FullName.SubString(m_root_b.Length).GetHashCode();
else
throw Exception("Invalid File. This file is not a part of the directories compared.");
}
更新
基于来自@Rufus的评论
根据CA1065: Do not raise exceptions in unexpected locations中的指定文章它指出
GetHashCode方法:Object.GetHashCode
和IEqualityComparer.GetHashCode(Object)
方法应该“通常”不引发异常。
[BUT] >>
如果我正在开发此应用程序,并且要确保
仅比较指定目录中的文件,我肯定会抛出异常。GetHashCode
方法返回int
,而Windows允许uint
(4x10 ^ 10)个文件。而且,如果有人(知道吗?)尝试破坏代码,则肯定会发生哈希冲突,从而导致错误匹配。而且我不喜欢这样的机会。相反,我会丢失哈希表,向用户/开发人员显示错误消息,并要求他/她重新开始。