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

时间:2012-01-20 08:13:51

标签: 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) - 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时间过长,我的webhost关闭了我的网站24小时。

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

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

编辑:

要指定,我正在处理游戏的设置文件。设置及其值位于设置前有32位int的块中,然后是设置,值前面的32位int,然后是值。两个int都表示以下字符串的长度。例如,如果设置为&#34; test&#34;它的值是&#34; 0&#34;,它看起来像(十六进制):00000004746573740000000130。现在你提到它,这看起来似乎是一个不好的方法去做。你会推荐什么?

编辑2:

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

编辑3:回复查尔斯:

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

1 个答案:

答案 0 :(得分:2)

你有很多垃圾代码。例如,这段代码几乎没有做任何事情:

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

因为它从文件的开头每次读取。此外,如果你没有回来,为什么还需要阅读?你可以为fseek()而烦恼吗?

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

但是,如果你要解析游戏的设置文件,我建议你使用fseek()fread()unpack()来寻找一个地方设置是,读取字节的一部分并将其解压缩到PHP的变量类型。