我有一些代码在每行上对带有排序十六进制值(SHA1哈希)的文件进行二进制搜索 . 这用于搜索HaveIBeenPwned数据库 . 最新版本包含每个密码哈希的查找次数,因此某些行末尾有额外的字符,格式为':###'
这个附加检查的长度不固定,并不总是存在 . 这会导致缓冲区读取不正确的值,并且无法找到实际存在的值 .
当前代码:
static bool Check(string asHex, string filename)
{
const int LINELENGTH = 40; //SHA1 hash length
var buffer = new byte[LINELENGTH];
using (var sr = File.OpenRead(filename))
{
//Number of lines
var high = (sr.Length / (LINELENGTH + 2)) - 1;
var low = 0L;
while (low <= high)
{
var middle = (low + high + 1) / 2;
sr.Seek((LINELENGTH + 2) * ((long)middle), SeekOrigin.Begin);
sr.Read(buffer, 0, LINELENGTH);
var readLine = Encoding.ASCII.GetString(buffer);
switch (readLine.CompareTo(asHex))
{
case 0:
return true;
case 1:
high = middle - 1;
break;
case -1:
low = middle + 1;
break;
default:
break;
}
}
}
return false;
}
我的想法是从中间向前寻找直到找到换行符,然后向后寻找相同的点,这应该给我一个完整的行,我可以通过':'分隔符分割 . 然后我比较分裂字符串数组的第一部分,它应该只是一个SHA1哈希 .
我认为这仍然应该以正确的 Value 为中心,但我想知道是否有更简洁的方法来做到这一点?如果中点不是行尾字符之间的实际中点,是否应该在高值和低值之前进行调整?
1 回答
我认为这可能是一个更简单(更快)的解决方案,没有回溯到线的开头 . 我认为你可以使用字节文件索引,而不是尝试使用完整的“记录/行 . 因为中间索引不会总是在行/记录的开头,”readline“可以返回部分行/记录如果你要立即做第二个“readline”,你会得到一个完整的行/记录 . 这不是最佳的,因为你实际上会比中间索引略微一点 .
我下载了pwned-passwords-update-1并在开始,结束和中间提取了大约30条记录,它似乎找到了所有记录 . 你怎么看?