C# 如果一个字节数组数组包含另一个字节数组,最快的方法是什么?
我有一些非常慢的代码。我知道会的,现在是了。基本上,我从一堆目录中读取文件。文件名会更改,但数据不会更改。为了确定是否已读取该文件,我对其字节进行散列,并将其与已处理文件的散列列表进行比较。每个目录中大约有1000个文件,弄清楚每个目录中有什么新内容需要一分钟左右的时间(然后处理开始)。以下是基本代码:C# 如果一个字节数组数组包含另一个字节数组,最快的方法是什么?,c#,comparison,reference-type,bytearray,C#,Comparison,Reference Type,Bytearray,我有一些非常慢的代码。我知道会的,现在是了。基本上,我从一堆目录中读取文件。文件名会更改,但数据不会更改。为了确定是否已读取该文件,我对其字节进行散列,并将其与已处理文件的散列列表进行比较。每个目录中大约有1000个文件,弄清楚每个目录中有什么新内容需要一分钟左右的时间(然后处理开始)。以下是基本代码: public static class ProgramExtensions { public static byte[] ToSHA256Hash(this FileInfo file)
public static class ProgramExtensions
{
public static byte[] ToSHA256Hash(this FileInfo file)
{
using (FileStream fs = new FileStream(file.FullName, FileMode.Open))
{
using (SHA256 hasher = new SHA256Managed())
{
return hasher.ComputeHash(fs);
}
}
}
public static string ToHexString(this byte[] p)
{
char[] c = new char[p.Length * 2 + 2];
byte b;
c[0] = '0'; c[1] = 'x';
for (int y = 0, x = 2; y < p.Length; ++y, ++x)
{
b = ((byte)(p[y] >> 4));
c[x] = (char)(b > 9 ? b + 0x37 : b + 0x30);
b = ((byte)(p[y] & 0xF));
c[++x] = (char)(b > 9 ? b + 0x37 : b + 0x30);
}
return new string(c);
}
}
class Program
{
static void Main(string[] args)
{
var allFiles = new DirectoryInfo("c:\\temp").GetFiles("*.*");
List<string> readFileHashes = GetReadFileHashes();
List<FileInfo> filesToRead = new List<FileInfo>();
foreach (var file in allFiles)
{
if (readFileHashes.Contains(file.ToSHA256Hash().ToHexString()))
filesToRead.Add(file);
}
//read new files
}
}
公共静态类程序扩展
{
公共静态字节[]tosha256散列(此FileInfo文件)
{
使用(FileStream fs=newfilestream(file.FullName,FileMode.Open))
{
使用(SHA256 hasher=new SHA256Managed())
{
返回hasher.ComputeHash(fs);
}
}
}
公共静态字符串到HexString(此字节[]p)
{
char[]c=新字符[p.Length*2+2];
字节b;
c[0]=“0”;c[1]=“x”;
对于(int y=0,x=2;y>4));
c[x]=(字符)(b>9?b+0x37:b+0x30);
b=((字节)(p[y]&0xF));
c[++x]=(字符)(b>9?b+0x37:b+0x30);
}
返回新字符串(c);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var allFiles=new DirectoryInfo(“c:\\temp”).GetFiles(“*”);
List readFileHashes=GetReadFileHashes();
List filesToRead=新列表();
foreach(所有文件中的var文件)
{
if(readFileHashes.Contains(file.tosha256 hash().ToHexString()))
添加(文件);
}
//读取新文件
}
}
有什么方法可以加快速度吗?我会先做一个快速的CRC哈希检查,因为它比较便宜。
如果CRC不匹配,继续进行更“可靠”的哈希测试,例如SHA我相信您可以通过首先检查文件大小来归档最显著的性能改进,如果文件大小不匹配,您可以跳过整个文件,甚至不打开它 除了保存已知散列的列表外,您还可以保留已知文件大小的列表,并且仅在文件大小匹配时进行内容比较。当文件大小不匹配时,您甚至可以避免查看文件内容 根据文件的一般大小,进一步的改进是值得的:
- 当第一个字节不同时,执行二进制比较或提前中止(节省读取整个文件的时间,这可能是一个非常显著的改进,如果您的文件通常较大,任何哈希算法都会读取整个文件。检测到第一个字节不同,则节省读取文件其余部分的时间)。如果您的查找文件列表可能包含许多大小相同的文件,因此您可能需要对多个文件进行二进制比较,请考虑:
- 以块为单位进行散列,每个块为1MB。首先,仅根据查找中预先计算的第一个块哈希值检查第一个块。如果第一个块相同,则仅比较第二个块,在大多数情况下,对于不同的文件,在第一个块之外保存读取。只有当文件很大时,这两个选项才真正值得付出努力
- 创建一个文件列表
- 按文件大小对列表排序
- 从列表中删除具有唯一大小的文件
- 现在做散列(首先快速散列也可以提高性能)
- 为readFileHashes存储使用具有高效搜索功能(哈希或二进制搜索)的数据结构。我想HashSet或TreeSet在这里更适合你
- 使用适当的校验和(哈希和)函数。SHA256是一个加密散列,可能是杀伤力过大。CRC的计算成本较低,最初用于捕获无意/随机更改(传输错误),但可接受设计/打算隐藏的更改。您正在扫描的文件之间的差异是什么 看 通过采样实现的简单校验和(例如校验和=(前10个字节和后10个字节))有效吗
- 您对问题的描述仍然不够清楚
最大的问题是,您正在进行大量的哈希运算。这肯定是缓慢的
您可能希望尝试搜索修改时间,如果文件名更改,修改时间不会更改:
或者,您可能希望监视文件夹中的任何新文件更改: