分割可变大小块的大多数内存效率高的方法?

时间:2014-01-14 18:21:59

标签: php split fread

有没有办法像fread那样做,但是在变量上呢? 也就是说,我希望一次“读取”另一个内存变量1MB。

这样我可以得到这样的东西:

$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);

我有一个大的二进制文件加载到内存中,大约10MB。我想将它拆分成1MB块的数组。我一次不需要内存中的所有1MB块,所以我认为我可以比使用PHP的内置str_split函数更有效地执行上述操作。

2 个答案:

答案 0 :(得分:1)

你可以使用like;

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

答案 1 :(得分:1)

没有办法顺序“读取”已经加载到内存中的字符串;拆分它并不是更有效率。多个变量的开销将使用比单个变量更多的内存。理想情况下,您将字符串加载到流中,但PHP实际上没有字符串流。

如果你只想处理块中的字符串,你可以循环遍历它的子串:

$data;
$pointer = 0, $size = strlen($data);

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

我不确定PHP如何在内部处理大字符串,但根据string documentation,字符串只能“最大2GB(最大2147483647字节)”。如果您的文件大约是10MB,那对PHP来说应该不是问题。

另一个选项(可能是更好的选项)是将$data加载到memory or temporary stream。如果要从过多的内存中节省环境,可以使用php://temp流包装器,其中一些数据存储在临时文件中(如果超过2MB)。只需将字符串尽快加载到流中以节省内存,然后就可以使用文件流功能了。

$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!
...

如果你想将它全部留在内存中,你可以使用php://memory,但在这种情况下你也可以使用一个字符串。