没有办法按顺序“读取”已加载到内存中的字符串;分裂它并不是真的更高效。多个变量的开销也会比单个变量更多地使用内存。理想情况下,您可以将字符串加载到流中,但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
,但是你可能也只是使用在这种情况下一个字符串。
这两种方法都可以工作。不幸的是,我对两种方法进行了基准测试,实际上它们比str_split慢*,所以我只是保持代码的方式。 :)尽管谢谢你非常透彻的答案! 仅供参考,'php:// memory'的数量级比'str_split'慢了几个数量级,而'substr'方法几乎与w /'str_split'差不多。然而,'str_split'只是几乎没有更快 - 并且读取/维护更容易。 最终结果:保持一切! – DOOManiac
@DOOManiac:我想到虚拟流会比较慢 - 使用'php:// temp'后面的想法是它有更高的内存效率。即使将它全部存储在内存中,我敢打赌它使用的是原始C字节数组,而不是更方便但消耗更多内存的“$ string”。使用流和大块阅读功能可以防止你的记忆真的很高。如果这不是你的目标,那么'str_split'可能是你最好的选择。 ;) – coderstephen
我的目标是速度,纯粹和简单。尽管谢谢你的回答! – DOOManiac