Я хочу найти определенную последовательность байтов в двоичном файле с помощью PHP. Я представлял эту последовательность в шестнадцатеричной форме, чтобы не набирать слишком много 0 и 1. Последовательность поиска - 0x4749524f
. Это рабочий раствор я придумал сейчас:Поиск последовательности байтов в двоичном файле в PHP?
$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 байта
- Проверьте, если они равно последовательности
- Если они равны -> найдено! Прекратите выполнение.
- Если они не равны, и я не в конце файла, вернитесь 3 байт в файл и повторите шаг 1.
Почему я возвращаюсь 3 байт? Потому что, если это содержимое файла:
0000 4749 524f 0000 01b0 0013
Если я не идут назад 3 байта, я буду читать 0000 4749
на первой итерации, 524f 0000
на второй, 01b0 0013
на третий и, как вы можете видеть я пропустил последовательность.
Проблема: медленно, как ад ... Приложению придется работать с файлами размером до 50 МБ, поэтому на этой последовательности понадобится навсегда.
Есть ли оптимизированная функция в PHP, которая бы выполняла эту работу? Есть ли более быстрый (не тупой, как мой) способ сделать это?
Читайте в длинном наборе байтов, что-то вроде 1M (или больше). Затем выполните поиск в памяти. При чтении следующих 1 Мбайт обязательно проверьте, были ли последние 3 первого набора началом иглы. –
Хорошо, я попробую! Благодарю. BTW, я думал, что файл был кэширован в memry во время чтения ... вы имеете в виду, что каждый раз, когда я запускаю функцию fread, файл читается непосредственно с жесткого диска? –
@AlbertoFontana Это просто модификация того же подхода, только чтение в больших кусках (я бы сказал, 4-8k), а затем «найти в куске» (vs «chunk exact match»). Чтобы легко справиться с расщепленными кусками, простым способом является поиск назад, так что куски на самом деле перекрываются несколькими байтами (этот закрытый поиск достаточно хорош, если делать относительно нечасто). Сокращение числа системных вызовов - это то, что будет самой большой разницей в производительности. Кроме того, немного больше работы может быть уменьшено путем преобразования $ mysequence в последовательность байтов, вместо того чтобы всегда преобразовывать прочитанные данные. – user2864740