我正在尝试扩展文件比较器,以从被比较文件的路径中减去根路径。问题出在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函数失败)。这个问题的解决方案是什么,或者我应该使用不同的方法来比较文件?这将用于比较大量文件,因此代码延迟很重要。
发布于 2020-05-30 07:16:33
由于您的比较器已经存储了两个根路径,并且只希望将这些路径中的文件传递给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)方法“通常”不应该抛出异常。
而不是
如果我正在开发这个应用程序,并且为了确保只比较指定目录中的文件,我肯定会抛出一个异常。
如果开发人员有意或无意地比较两个不同文件夹中的文件,而这两个文件夹中的一个或两个没有使用初始化对象的原因,则文件比较完全是invalid.
int,而GetHashCode允许uint (4x10^10)个文件。如果有人(谁知道呢?)尝试破解代码,肯定会有哈希冲突,从而导致错误匹配;我不喜欢冒这样的风险。相反,我会同意丢失Hashtable,向用户/开发人员显示一条错误消息,并要求他/她重新开始。
https://stackoverflow.com/questions/62095077
复制相似问题