php flush类输出缓冲剖析


Posted in PHP onOctober 19, 2008

<?php
for ($i=10; $i>0; $i--)
{
echo $i;
flush();
sleep(1);
}
?>
按照php手册里的说法
该函数将当前为止程序的所有输出发送到用户的浏览器。
上面的这段代码,应该隔一秒钟输出一次$i。但是实际中却不一定是这样。有可能是等了10秒钟后,所有的输出同时呈现出来。
好,我们来改一下这段代码,改成
<?php
ob_end_clean();//修改部分
for ($i=10; $i>0; $i--)
{
echo $i;
flush();
sleep(1);
}
?>
嘿,加了这一句ob_end_clean();,居然就OK了。实际上,我们把ob_end_clean()换成ob_end_flush()也一样OK。
我再来改一改。
<?php
for ($i=10; $i>0; $i--)
{
echo $i;
ob_flush();//修改部分
flush();
sleep(1);
}
?>
运行一下,是不是发现$i也隔一秒输出一次了?这是为什么呢?
别急,我们来看看php.ini。
打开php.ini,搜索output_buffering,我们会看到类似这样的设置 output_buffering = 4096。正如它的名字output_buffering一样,这个设置的作用就是把输出缓冲一下,缓冲大小为4096bytes.
在我们的第一段代码里,之所以没有按预期的输出,正是因为这个output_buffering把那些输出都缓冲了。没达到4096bytes或者脚本结束,输出是不会被发送出去的。
而第二段代码中的ob_end_clean()和ob_end_flush()的作用,就是终止缓冲。这样就不用等到有4096bytes的缓冲之后才被发送出去了。
第三段代码中,用了一句ob_flush(),它的作用就是把缓冲的数据发送出去,但是并不会终止缓冲,所以它必须在每次flush()前使用。
如果不想使用ob_end_clean(),ob_end_flush()和ob_flush(),我们就必须把php.ini里的 output_buffering设得足够小,例如设为0。需要注意的是,如果你打算在脚本中使用ini_set(” output_buffering”,”0″)来设置,那么请停下来吧,这种方法是不行的。因为在脚本一开始的时候,缓冲设置就已经被载入,然后缓冲就开始了。
可能你会问了,既然ob_flush()是把缓冲的数据发送出去,那么为什么还需要用flush()???直接用下面这段代码不行吗??
<?php
for ($i=10; $i>0; $i--)
{
echo $i;
ob_flush();
sleep(1);
}
?>
请注意ob_flush()和flush()的区别。前者是把数据从PHP的缓冲中释放出来,后者是把不在缓冲中的或者说是被释放出来的数据发送到浏览器。所以当缓冲存在的时候,我们必须ob_flush()和flush()同时使用。
那是不是flush()在这里就是不可缺少的呢?不是的,我们还有另外一种方法,使得当有数据输出的时候,马上被发送到浏览器。下面这两段代码就是不需要使用flush()了。(当你把output_buffering设为0的时候,连ob_flush()和ob_end_clean()都不需要了)
<?php
ob_implicit_flush(true);
for ($i=10; $i>0; $i--)
{
echo $i;
ob_flush();
sleep(1);
}
?>
<?php
ob_end_clean();
ob_implicit_flush(true);
for ($i=10; $i>0; $i--)
{
echo $i;
sleep(1);
}
?>
请注意看上面的ob_implicit_flush(true),这个函数强制每当有输出的时候,即刻把输出发送到浏览器。这样就不需要每次输出(echo)后,都用flush()来发送到浏览器了。
以上所诉可能在某些浏览器中不成立。因为浏览器也有自己的规则。我是用Firefox1.5,IE6,opera8.5来测试的。其中opera就不能正常输出,因为它有一个规则,就是不遇到一个HTML标签,就绝对不输出,除非到脚本结束。而FireFox和IE还算比较正常的。
最后附上一段非常有趣的代码,作者为PuTTYshell。在一个脚本周期里,每次输出,都会把前一次的输出覆盖掉。
以下代码只在firefox下可用,其他浏览器并不支持multipart/x-mixed-replace的Content-Type.
<?php
header('Content-type: multipart/x-mixed-replace;boundary=endofsection');
print "\n--endofsection\n";
$pmt = array("-", "\\", "|", "/" );
for( $i = 0; $i <10; $i ++ ){
sleep(1);
print "Content-type: text/plain\n\n";
print "Part $i\t".$pmt[$i % 4];
print "--endofsection\n";
ob_flush();
flush();
}
print "Content-type: text/plain\n\n";
print "The end\n";
print "--endofsection--\n";
?>

PHP 相关文章推荐
PHP 用数组降低程序的时间复杂度
Dec 04 PHP
解析php函数method_exists()与is_callable()的区别
Jun 21 PHP
php从memcache读取数据再批量写入mysql的方法
Dec 29 PHP
PHP使用flock实现文件加锁的方法
Jul 01 PHP
php使用pear_smtp发送邮件
Apr 15 PHP
PHP使用FFmpeg获取视频播放总时长与码率等信息
Sep 13 PHP
php分页查询mysql结果的base64处理方法示例
May 18 PHP
PHP十六进制颜色随机生成器功能示例
Jul 24 PHP
详解PHP文件的自动加载(autoloading)
Feb 04 PHP
Laravel框架生命周期与原理分析
Jun 12 PHP
使用laravel和ECharts实现折线图效果的例子
Oct 09 PHP
php传值和传引用的区别点总结
Nov 19 PHP
PHP5+UTF8多文件上传类
Oct 17 #PHP
Zend studio for eclipse中使php可以调用mysql相关函数的设置方法
Oct 13 #PHP
PHP中str_replace函数使用小结
Oct 11 #PHP
php preg_match_all结合str_replace替换内容中所有img
Oct 11 #PHP
php email邮箱正则
Oct 08 #PHP
php获取地址栏信息的代码
Oct 08 #PHP
Cannot modify header information错误解决方法
Oct 08 #PHP
You might like
了解Joomla 这款来自国外的php网站管理系统
2010/03/11 PHP
PHP extract 将数组拆分成多个变量的函数
2010/06/30 PHP
PHP管理内存函数 memory_get_usage()使用介绍
2012/09/23 PHP
php获取目标函数执行时间示例
2014/03/04 PHP
php解决约瑟夫环示例
2014/04/09 PHP
PHP控制前台弹出对话框的实现方法
2016/08/21 PHP
php 时间time与日期date之间的使用详解及区别
2016/11/07 PHP
jsp js鼠标移动到指定区域显示选项卡离开时隐藏示例
2013/06/14 Javascript
Jquery实现图片放大镜效果的思路及代码(自写)
2013/10/18 Javascript
[将免费进行到底]在Amazon的一年免费服务器上安装Node.JS, NPM和OurJS博客
2014/08/18 Javascript
jQuery控制li上下循环滚动插件用法实例(附demo源码下载)
2016/05/28 Javascript
Angular ng-repeat 对象和数组遍历实例
2016/09/14 Javascript
Query常用DIV操作获取和设置长度宽度的实现方法
2016/09/19 Javascript
微信小程序开发(二)图片上传+服务端接收详解
2017/01/11 Javascript
通过npm引用的vue组件使用详解
2017/03/02 Javascript
JS中cookie的使用及缺点讲解
2017/05/13 Javascript
详解Angular6.0使用路由步骤(共7步)
2018/06/29 Javascript
layui实现二维码弹窗、并下载到本地的方法
2019/09/25 Javascript
使用vue-cli4.0快速搭建一个项目的方法步骤
2019/12/04 Javascript
JavaScript 中的无穷数(Infinity)详解
2020/02/13 Javascript
js对象属性名驼峰式转下划线的实例代码
2020/09/17 Javascript
[06:45]DOTA2卡尔工作室 英雄介绍幻影长矛手篇
2013/07/12 DOTA
Python中super函数的用法
2017/11/17 Python
Python比较2个时间大小的实现方法
2018/04/10 Python
Python定时发送消息的脚本:每天跟你女朋友说晚安
2018/10/21 Python
python获取点击的坐标画图形的方法
2019/07/09 Python
python base64库给用户名或密码加密的流程
2020/01/02 Python
django为Form生成的label标签添加class方式
2020/05/20 Python
一款纯css3实现的tab选项卡的实列教程
2014/12/11 HTML / CSS
竞聘演讲稿范文
2014/01/12 职场文书
清华大学自主招生自荐信
2014/01/29 职场文书
德语专业求职信
2014/03/12 职场文书
松材线虫病防治方案
2014/06/15 职场文书
书法社团活动总结
2015/05/07 职场文书
员工加薪申请报告
2015/05/15 职场文书
阿里云 Windows server 2019 配置FTP
2022/04/28 Servers