我想使用 PHP 在二进制文件中查找特定的字节序列。我用十六进制表示这个序列,以避免输入太多的 0 和 1。要查找的序列是 0x4749524f
。这是我现在提出的工作解决方案:
$mysequence = "4749524f";
$f = fopen($filename, "r") or die("Unable to open file!");
while(!feof($f)) {
$seq = fread($f, 4);
if(bin2hex($seq) == $mysequence) {
echo "found!";
break;
}
else if(!feof($f)) fseek($f, -3, SEEK_CUR);
}
算法的作用很简单:
- 读取 4 个字节
- 检查它们是否等于序列
- 如果它们相等 -> 找到了!停止执行。
- 如果它们不相等且 i 不在文件末尾,则返回文件中的 3 个字节并重复步骤 1。
为什么我要返回 3 Bytes?因为如果这是文件的内容:
0000 4749 524f 0000 01b0 0013
如果我不返回 3 字节,我将在第一次迭代时读取 0000 4749
,在第二次迭代时读取 524f 0000
,01b0 0013
在第三个,如你所见,我错过了序列。
问题:它慢得要命......应用程序将不得不处理最大 50MB 的文件,因此要花很长时间才能找到这个序列。
PHP 中是否有优化函数可以完成这项工作?有没有更快(不像我这样笨)的方法来做到这一点?
最佳答案
首先是你的$mysequence
搜索时没有变化,所以你可以调用hex2bin($mysequence)
一次并将其与 $seq
进行比较直接地。
至于真的更快,您可以尝试在大缓冲区中读取和搜索字符串。更大的缓冲区 => 更快的搜索,但需要更多的内存。快速代码草稿,它应该是什么样子:
$mysequence = "4749524f";
$searchBytes = hex2bin($mysequence);
$crossing = 1 - length($searchBytes); // - (length - 1); see below
$buf = ''; $buflen = 10000;
$f = fopen($filename, "r") or die("Unable to open file!");
while(!feof($f))
{
$seq .= fread($f, $buflen);
if(strpos($seq, $searchBytes) === false) // strict comparation here. zero can be returned!
{
// keep last n-1 bytes, because they can be beginning of required sequence
$seq = substr($seq, $crossing);
}
else
{
echo "found!";
break;
}
}
unset($seq); // no need to keep this in memory any more
关于php - 在 PHP 中的二进制文件中搜索字节序列?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32487031/