一个国家强大了,别的国家都会来跟你建交;一个人强大了,别的人都会跟你友好,一个男人强大了,好女孩自然会来找你。所以,不要苦苦地等一个人,不要为无法赢得一个人的心而懊丧,应加强自身建设。
准备
PHP已经为我们提供了函数memory_get_peak_usage
,用来返回脚本运行过程中分配给 PHP 内存的峰值.单位是字节, 我们需要写一个函数将这个结果转化为我们可以轻易理解的单位, 比如MB
;
memory.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
function formatBytes($bytes, $precision = 2) { $units = array("b", "kb", "mb", "gb", "tb");
$bytes = max($bytes, 0); $pow = floor(($bytes ? log($bytes) : 0) / log(1024)); $pow = min($pow, count($units) - 1);
$bytes /= (1 << (10 * $pow));
return round($bytes, $precision) . " " . $units[$pow]; }
print formatBytes(memory_get_peak_usage());
|
然后我们准备了一个存有59w个邮箱的txt文件, 文本大小13M;
使用fgets
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
function readTheFile($path) { $handle = fopen($path, "r");
while(!feof($handle)) { echo trim(fgets($handle)).PHP_EOL; } fclose($handle); }
readTheFile("59w.txt");
require "memory.php";
|
结果: 62.35 mb
使用生成器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <?php
function readTheFile($path) { $handle = fopen($path, "r");
while(!feof($handle)) { yield trim(fgets($handle)).PHP_EOL; } fclose($handle); }
$iterator = readTheFile("59w.txt");
foreach ($iterator as $iteration) { echo $iteration; }
require "memory.php";
|
结果: 382.88 kb
管道间的文件
在我们不需要处理数据的情况下,我们可以把文件数据传递到另一个文件。通常被称为管道(大概是因为我们看不到除了两端的管子里面,当然,它也是不透明的),我们可以通过使用流方法实现。让我们先写一个脚本从一个文件传到另一个文件。这样我们可以测量内存的占用情况:
1 2 3 4 5 6 7
| <?php
file_put_contents( "test1.txt", file_get_contents("59w.txt") );
require "memory.php";
|
结果: 14.34 mb
让我们尝试用流(管道)来传送一个文件到另一个:
1 2 3 4 5 6 7 8 9 10 11
| <?php
$handle1 = fopen("59w.txt", "r"); $handle2 = fopen("test2.txt", "w");
stream_copy_to_stream($handle1, $handle2);
fclose($handle1); fclose($handle2);
require "memory.php";
|
结果: 381.77 kb
https://www.oschina.net/translate/performant-reading-big-files-php