我正在将媒体文件转换为新格式,并且需要一种方法来了解我之前在当前运行时是否转换过文件。
散列每个文件并将散列存储在数组中。每次我转换文件时,我都会对其进行哈希处理,并根据存储在数组中的哈希检查哈希值。
我的逻辑似乎无法检测到我已经看过文件的时间,并且我最终会多次转换同一个文件。
//Byte array of already processed files
private static readonly List<byte[]> Bytelist = new List<byte[]>();
public static bool DoCheck(string file)
{
FileInfo info = new FileInfo(file);
while (FrmMain.IsFileLocked(info)) //Make sure file is finished being copied/moved
{
Thread.Sleep(500);
}
//Get byte sig of file and if seen before dont process
byte[] myFileData = File.ReadAllBytes(file);
byte[] myHash = MD5.Create().ComputeHash(myFileData);
if (Bytelist.Count != 0)
{
foreach (var item in Bytelist)
{
//If seen before ignore
if (myHash == item)
{
return true;
}
}
}
Bytelist.Add(myHash);
return false;
}
是否有更有效的方法来实现我的最终目标?我做错了什么?
答案 0 :(得分:2)
有很多问题,我将回答第一个问题:
是否有更有效的方法来实现我的最终目标?
TL; DR是的。
您正在存储哈希值并仅为文件比较哈希值,这是一项非常昂贵的操作。您可以在计算哈希值之前进行其他检查:
当然,您必须为每个已处理的文件存储大小/前X个字节/哈希值。
此外,同样的 MD5 并不意味着文件是相同的,所以您可能需要采取额外的步骤来检查它们是否真的相同,但这可能是一种过度杀伤,取决于重新处理文件的成本有多大,可能更重要的是不计算昂贵的哈希值。
编辑:第二个问题:可能会失败,因为您要比较两个字节数组的引用,这些引用永远不会与您每次创建新数组相同,您需要创建序列相等 byte [] 之间的比较。 (或者将哈希值转换为字符串并比较字符串)
var exists = Bytelist.Any(hash => hash.SequenceEqual(myHash));
答案 1 :(得分:1)
答案 2 :(得分:1)
在效率,效果和风格方面还有很大的改进空间,但这不是CodeReview.SE,所以我会尝试解决手头的问题:
您使用==运算符检查两个字节的数组是否相等。但这只会执行引用相等测试 - 即测试两个变量是否指向同一实例,即同一个数组。当然,这不会在这里工作。
有很多方法可以做到这一点,从数组上的简单foreach
循环开始(可能是首先检查长度的优化)或使用Enumerable.SequenceEquals
,如Convert.ToBase64String
所示。 3}}
更好的是,将哈希的byte []转换为字符串(任何字符串 - private static readonly HashSet<string> _computedHashes = new HashSet<string>();
public static bool DoCheck(string file)
{
/// stuff
//Get byte sig of file and if seen before dont process
byte[] myFileData = File.ReadAllBytes(file);
byte[] myHash = MD5.Create().ComputeHash(myFileData);
string hashString = Convert.ToBase64String(myHash);
return _computedHashes.Contains(hashString);
}
都是一个不错的选择)并将 存储在Bytelist缓存中(应该是Hashset,而不是List。字符串针对这些比较进行了优化,您不会遇到&#34;参考相等&#34;问题在这里。
所以样本解决方案就是这样:
{{1}}
据推测,您在完成转换后将哈希添加到_computedHashes集。
答案 3 :(得分:0)
您必须逐项比较字节数组:
foreach (var item in Bytelist)
{
//If seen before ignore
if (myHash.Length == item.Length)
{
bool isequal = true;
for (int i = 0; i < myHash.Length; i++)
{
if (myHash[i] != item[i])
{
isequal = false;
}
}
if (isequal)
{
return true;
}
}
}