Самый эффективный с точки зрения памяти способ разделить куски переменной величины?

Есть ли способ сделать что-то вроде fread , но по переменной? То есть, я хочу «читать» другую переменную памяти 1 МБ за раз.

Таким образом, я мог бы что-то вроде этого:

 $data = ... ; // 10MB of data $handle = fopen($data, "rb"); // Need something instead of fopen here while (!feof($handle)) { $chunk = fread($handle, 1048576); // Want to read 1MB at a time doSomethingWithChunk($chunk); } fclose($handle); 

У меня есть большой двоичный файл, загруженный в память, около 10 МБ. Я бы хотел разбить его на массив из 1 Мбайт кусков. Мне не нужны все 1MB куски в памяти сразу, поэтому я думаю, что я мог бы сделать что-то подобное выше более эффективно, чем просто использовать встроенную функцию str_split PHP .

Невозможно последовательно «прочитать» строку, которая уже загружена в память; это не более эффективно разделить его. Накладные расходы нескольких переменных будут использовать больше памяти, чем один. В идеале вы загружаете строку в поток, но PHP не имеет потокового потока.

Если вы просто хотите иметь дело со строкой в ​​кусках, вы можете просто перебрать ее подстроки:

 $data; $pointer = 0, $size = strlen($data); $chunkSize = 1048576; while ($pointer < $size) { $chunk = substr($data, $pointer, $chunkSize); doSomethingWithChunk($chunk); $pointer += $chunkSize; } 

Я не уверен, как PHP обрабатывает большие строки внутри, но, согласно строковой документации , строка может быть «размером до 2 ГБ (максимум 2147483647 байт)». Если ваш файл составляет около 10 МБ, это не должно быть проблемой для PHP.

Другой вариант (вероятно, лучший вариант) – загрузить $data в память или временный поток . Если вы хотите избавить окружающую среду от избыточной памяти, вы можете использовать php://temp stream, где некоторые данные хранятся во временном файле, если он превышает 2 МБ. Просто загрузите строку в поток как можно скорее, чтобы сохранить память, а затем вы можете использовать функции потока файлов на ней.

 $dataStream = fopen("php://temp", "w+b"); fwrite($dataStream, funcThatGetsData()); // try not to put data into a variable to save memory while (!feof($dataStream)) { $chunk = fread($dataStream, 1048576); // want to read 1MB at a time doSomethingWithChunk($chunk); } fclose($dataStream); 

Если вы получите $data из другой функции, вы можете вместо этого использовать $dataStream . Если вы должны иметь $data в строке заранее, обязательно вызовите unset() на нем, чтобы освободить память:

 $data = getData(); // string from some other function $dataStream = fopen("php://temp", "w+b"); fwrite($dataStream, $data); unset($data); // free 10MB of memory! ... с $data = getData(); // string from some other function $dataStream = fopen("php://temp", "w+b"); fwrite($dataStream, $data); unset($data); // free 10MB of memory! ... 

Если вы хотите сохранить все это в памяти, вы можете использовать память php://memory , но в этом случае вы можете просто использовать строку.

Вы можете использовать как;

 $handle = @fopen("path_to_your_file", "r"); if ($handle) { while (($buffer = fgets($handle, 1024)) !== false) { doSomethingWithChunk($buffer ); } fclose($handle); }