Есть ли способ сделать что-то вроде 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); }