在php中搜索文件中的十六进制字符串?

在php中搜索文件中的十六进制字符串?,php,performance,file,cpu,Php,Performance,File,Cpu,我目前在课堂上使用以下两种方法来完成任务: function xseek($h,$pos){ rewind($h); if($pos>0) fread($h,$pos); } function find($str){ return $this->startingindex($this->name,$str); } function startingindex($a,$b){ $lim = 1 + filesize($a) - strle

我目前在课堂上使用以下两种方法来完成任务:

function xseek($h,$pos){
    rewind($h);
    if($pos>0)
    fread($h,$pos);
}
function find($str){
    return $this->startingindex($this->name,$str);
}

function startingindex($a,$b){
    $lim = 1 + filesize($a) - strlen($b)/2;
    $h = fopen($a,"rb");
    rewind($h);
    for($i=0;$i<$lim;$i++){
        $this->xseek($h,$i);
        if($b==strtoupper(bin2hex(fread($h,strlen($b)/2)))){
            fclose($h);
            return $i;
        }
    }
    fclose($h);
    return -1;
}
函数xseek($h,$pos){
倒带($h);
如果($pos>0)
fread($h,$pos);
}
函数find($str){
返回$this->startingindex($this->name,$str);
}
函数启动索引($a,$b){
$lim=1+文件大小($a)-strlen($b)/2;
$h=fopen($a,“rb”);
倒带($h);
对于($i=0;$ixseek($h,$i);
如果($b==strtoupper(bin2hex(fread($h,strlen($b)/2))){
fclose(小时);
返回$i;
}
}
fclose(小时);
返回-1;
}
我意识到这是非常低效的,尤其是对于PHP,但我的托管计划中不允许使用任何其他语言

我运行了几个测试,当十六进制字符串指向文件开头时,它会快速运行并返回偏移量。但是,当找不到十六进制字符串时,页面会挂起一段时间。这会让我很伤心,因为上次我用PHP测试并挂起页面时,我的Web主机由于cpu时间太长而关闭了我的站点24小时

是否有更好的方法来实现这一点(在文件中查找十六进制字符串的偏移量)?是否有某些方面可以改进以加快执行

我会将文件的全部内容读入一个十六进制字符串并使用strrpos,但我遇到了超过最大内存的错误。如果我将文件切碎并使用strrpos搜索大块,这是一种更好的方法吗

编辑:

具体来说,我正在处理一个游戏的设置文件。设置及其值位于一个块中,其中设置前有一个32位int,然后是设置,值前有一个32位int,然后是值。两个int表示以下字符串的长度。例如,如果设置为“test”,值为“0”,它看起来像(十六进制):0000000 4746573740000000130。既然你提到了它,这看起来确实是一个糟糕的方式。你会推荐什么

编辑2:

我尝试了一个低于允许的最大内存的文件,并尝试了strrpos,但它比我一直尝试的方式慢得多

编辑3:回复查尔斯:


未知的是设置块的长度及其起始位置。我知道的是第一个和最后一个设置通常是什么。我一直在使用这些搜索方法查找第一个和最后一个设置的位置,并确定设置块的长度。我还知道父块的起始位置。设置块是通用的我最多只能在父项中输入50个字节,因此我可以在那里开始搜索第一个设置,并限制它搜索的距离。问题是我还需要找到最后一个设置。设置块的长度是可变的,可以是任意长度。我可以像我假设的那样读取文件,通过读取设置的大小,读取设置,读取值的大小,读取值,等等。直到我到达一个值为-1的字节,或十六进制的FF。限制对第一个设置的搜索和正确读取设置的组合会使这更有效吗?

您有很多垃圾代码。例如,这段代码几乎没有任何作用:

function xseek($h,$pos){
    rewind($h);
    if($pos>0)
    fread($h,$pos);
}
因为它每次都从文件的开头开始读取。此外,如果你不返回它,为什么你需要读取一些内容?可能是你在寻找

如果您需要在二进制文件中查找十六进制字符串,最好使用以下内容:(如果有一些bug/问题,请告诉我)


但是,如果您正在解析游戏的设置文件,我建议您使用并查找设置所在的位置,读取部分字节并将其解压为PHP的变量类型。

您能告诉我们更多关于这个十六进制搜索例程的实际操作吗?看起来这与您关于拼接文件的问题直接相关还有。可能有更好的方法来完成整个任务。@Charles,我正在处理一个游戏的设置文件。设置及其值位于一个块中,其中设置前有一个32位int,然后是设置,值前有一个32位int,然后是值。这两个int都表示以下字符串的长度。例如,如果设置为“test”且值为“0”,则看起来像(十六进制):
0000000 4746573740000000130
。既然你提到了这一点,这似乎是一个不好的做法。你会推荐什么?就像所有事情一样,这有点取决于。你提到当要在文件中找到的字符串更深时,性能会下降。文件会变得多大?你要找的东西是否散落在整个文件中,还是它们在相对可预测的位置?@Charles,回答很长,所以我把它放在了帖子中。晚上有点太晚了(erk,一大早)要编写我想写的响应,那么,tl;dr:十六进制转换很愚蠢,使用
chr
ord
。使用
fseek
。进一步研究文件格式。如果您要查找的部分位置不同,但它有一个部分指示它有多大,那么文件中的其他块也可能有类似的大小节。利用这一点编写真正理解文件的代码,而不是盲目地查找。如果您的web托管提供商的脚本超时时间小于30秒,请将您的钱花在其他地方。fseek在99%的情况下无法正常工作。我在PHP中处理过大量二进制数据,一切都很好。看起来rs现在正在工作,但不是更早。不确定它现在是否可靠。你知道是什么导致它不工作吗?是因为文件还是其他条件吗?我使用的seek更可靠,但效率更低吗?你使用的seek的性能比
fseek()低得多
:它正在寻找零位,然后将数据从零位读取到
$pos
。这会浪费RAM和CPU,因为您不需要此数据