Во-первых, вы должны понимать, что при использовании file_get_contents вы извлекаете всю строку данных в переменную , что переменная хранится в памяти хоста.
если эта строка больше размера, выделенного для процесса PHP, тогда PHP остановится и отобразит сообщение об ошибке выше.
Способ обойти это, чтобы открыть файл в качестве указателя, а затем взять порцию за раз. Таким образом, если у вас есть файл размером 500 МБ, вы можете прочитать первые 1 МБ данных, делать то, что вы хотите с ним, удалить это 1 МБ из системной памяти и заменить на следующие МБ. Это позволяет вам управлять объемом данных, помещаемых в память.
В качестве примера, если это можно увидеть ниже, я создам функцию, которая действует как node.js
function file_get_contents_chunked($file,$chunk_size,$callback)
{
try
{
$handle = fopen($file, "r");
$i = 0;
while (!feof($handle))
{
call_user_func_array($callback,array(fread($handle,$chunk_size),&$handle,$i));
$i++;
}
fclose($handle);
}
catch(Exception $e)
{
trigger_error("file_get_contents_chunked::" . $e->getMessage(),E_USER_NOTICE);
return false;
}
return true;
}
и затем используйте так:
$success = file_get_contents_chunked("my/large/file",4096,function($chunk,&$handle,$iteration){
/*
* Do what you will with the {&chunk} here
* {$handle} is passed in case you want to seek
** to different parts of the file
* {$iteration} is the section fo the file that has been read so
* ($i * 4096) is your current offset within the file.
*/
});
if(!$success)
{
//It Failed
}
Одна из проблем, с которой вы столкнетесь, заключается в том, что вы пытаетесь выполнить регулярное выражение несколько раз на чрезвычайно большом куске данных, причем не только это, но и ваше регулярное выражение создано для сопоставления всего файла.
При использовании описанного выше метода ваше регулярное выражение может стать бесполезным, поскольку вы можете сопоставлять только половину набора данных, и вам нужно вернуться к собственным строковым функциям, таким как
strpos
substr
trim
explode
для сопоставления строк, я добавил поддержку в обратном вызове, так что дескриптор и текущая итерация пройдены, это позволит вам работать с файлом непосредственно в вашем обратном вызове, позволяя вам использовать такие функции, как fseek
, ftruncate
и fwrite
например.
То, как вы строите свои манипуляции со строками, неэффективно, и использование предложенного выше метода намного лучше.
Надеюсь, это поможет.