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


Searching for hex string in a file in php?

我目前在类中使用以下两种方法来完成任务:

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;
}

我意识到这是非常低效的,尤其是对于PHP,但我的托管计划中不允许使用任何其他语言。

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

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

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

编辑:

具体来说,我正在处理一个游戏的设置文件。设置及其值位于一个块中,其中在设置之前有一个32位的int,然后是设置,在值之前有一位32位的整型,然后是值。两个int表示以下字符串的长度。例如,如果设置为"test"并且值为"0",则它看起来像(十六进制):0000000 47465737400000130。既然你提到了,这似乎是一个糟糕的做法。你有什么建议吗?

编辑2:

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

编辑3:回复查尔斯:

未知的是设置块的长度及其起始位置。我所知道的是通常的第一个和最后一个设置是什么。我一直在使用这些搜索方法来查找第一个和最后一个设置的位置,并确定设置块的长度。我也知道父块从哪里开始。设置块通常不超过其父块的50个字节,所以我可以在那里开始搜索第一个设置,并限制它的搜索范围。问题是,我还需要找到最后一个设置。设置块的长度是可变的,可以是任何长度。我可以按照我认为游戏的方式读取文件,通过读取设置的大小、读取设置、读取值的大小、阅读值等,直到我达到值为-1的字节,或十六进制的FF。限制对第一个设置的搜索和正确读取设置的组合会使搜索更加高效吗?

您有很多垃圾代码。例如,这段代码几乎什么都没做:

function xseek($h,$pos){
    rewind($h);
    if($pos>0)
    fread($h,$pos);
}

因为它每次都从文件开始读取。此外,如果你不归还,为什么你需要读一些东西?你可以找fseek()吗?

如果你需要在二进制文件中找到一个十六进制字符串,最好使用这样的东西:http://pastebin.com/fpDBdsvV(如果有错误/问题,请告诉我)。

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