Home  >  Article  >  Backend Development  >  PHP逐行输出数据并解决两种常见缓冲有关问题

PHP逐行输出数据并解决两种常见缓冲有关问题

WBOY
WBOYOriginal
2016-06-13 12:14:331026browse

PHP逐行输出数据并解决两种常见缓冲问题

博主热衷各种互联网技术,常啰嗦,时常伴有强迫症,常更新,觉得文章对你有帮助的可以关注我。 转载请注明"深蓝的镰刀"


1.遇到问题

不知你们有没有碰到过这样两种情况:

  1. 老板要你将数据库中所有的数据在浏览器中展示出来,因为需要对比数据,老板要求是不能使用分页,那么好了,输出个1000条数据直接循环打印出来没问题,但是数据如果是几百万条呢?浏览器直接卡死,等你离开座位出去喝了杯咖啡,上了个厕所,和前台mm聊了个天,回来发现浏览器已经“程序未响应”了,你该怎么办?
  2. 老板让你改进一下网站的下载链接,要求直接鼠标左击就下载文件(某些文件类型,直接左击会打开这个文件,很多网站会提示你“右键另存为”),你用了header函数和readfile函数轻松实现了这个功能,但是上线后发现如果文件过大浏览器依旧会卡死,这次老板要请你喝咖啡了,你该怎么办?

好吧,如果你碰到了以上两种情况,或者你将来可能会面临这样的问题,你可以mark一下,以便下次快速解决。


2.原理


言归正传。


下面隆重推出PHP输出控制之输出缓冲区


首先,试一下下面代码的效果


<?phpif (ob_get_level() == 0){ ob_start() }else{ exit(0);};//开始缓冲for ($i = 0; $i<10; $i++){    echo "Line to show.\n<br />";//不直接输出,先存入缓冲区中    ob_flush();//将缓冲区的数据输出出来    flush();//将缓冲区的数据输出出来    sleep(2);//暂停两秒}echo "Done.";ob_end_flush();//关闭并清理缓冲区

想不到PHP也能实现这种延迟加载的功能吧,是不是很牛X的感觉。


原理的话就是PHP在输出数据前先将数据放进缓冲(Buffer)里,等待需要时我们再将缓冲的数据输出出来,注意一下这里不要跟缓存(Cache)混淆。


这样做的好处一方面可以实现类似延迟加载的炫酷效果,一方面也能够降低服务器和客户端的压力,不然输出大数据时就会出现内存不够用的情况。


注:ob_flush()flush()在用途上都是刷出缓冲区数据,但是官方建议配套使用因为虽然在大部分WebServer下只用ob_flush()就能刷出缓冲,但是在某些情况下如apache中有时需要调用flush()才行,所以为了你代码的可移植性,建议看到ob_flush()立马在后面加上flush()。


既然知道了原理,我们来解决开头提到的两个问题。


3.解决百万数据单页面输出卡死的问题

<?phpob_start ();$data = [1,2,3,4,5,6,7,8,9,10];//实际数据更多,为方便距离假设浏览器一次输出10条会卡死$per = 3;//每次输出3条,可以改成1000 for ($i = 0;$i < count($data); $i+= $per){    for($j = $i; $j < $i + $per && $j <count($data); $j++){        echo $data[$j];    }    ob_flush();    flush();    sleep(2);}echo "Done.";ob_end_flush();


4.解决header实现文件下载时文件过大导致卡死的问题

<?phpheader (&#39;Content-type: application/txt&#39;);//输出类型ob_start();$data = "qwertyuioasdfghjkl";//文件内容,file_get_contents($file)$per = 15;//每次输出15个字符,可以改成1000或更大 for ($i = 0;$i < strlen($data); $i+= $per){    for($j = $i; $j < $i + $per && $j <strlen($data); $j++){        echo $data[$j];    }    sleep(2);    ob_flush();    flush();}echo "Done.";     ob_end_flush(); 

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn