溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP中如何使用緩沖區(qū)

發(fā)布時(shí)間:2021-07-12 10:19:04 來(lái)源:億速云 閱讀:142 作者:Leah 欄目:開(kāi)發(fā)技術(shù)

PHP中如何使用緩沖區(qū),相信很多沒(méi)有經(jīng)驗(yàn)的人對(duì)此束手無(wú)策,為此本文總結(jié)了問(wèn)題出現(xiàn)的原因和解決方法,通過(guò)這篇文章希望你能解決這個(gè)問(wèn)題。

具體如下:

<?php
for ($i=10; $i>0; $i--)
{
  echo $i;
  flush();
  sleep(1);
}
?>

按照php手冊(cè)里的說(shuō)法:

該函數(shù)將當(dāng)前為止程序的所有輸出發(fā)送到用戶的瀏覽器。

上面的這段代碼,應(yīng)該隔一秒鐘輸出一次$i。但是實(shí)際中卻不一定是這樣。有可能是等了10秒鐘后,所有的輸出同時(shí)呈現(xiàn)出來(lái)。

好,我們來(lái)改一下這段代碼,改成

<?php
ob_end_clean();//修改部分
for ($i=10; $i>0; $i--)
{
  echo $i;
  flush();
  sleep(1);
}
?>

嘿,加了這一句ob_end_clean();,居然就OK了。實(shí)際上,我們把ob_end_clean()換成ob_end_flush()也一樣OK。

我再來(lái)改一改。

<?php
for ($i=10; $i>0; $i--)
{
  echo $i;
  ob_flush();//修改部分
  flush();
  sleep(1);
}
?>

運(yùn)行一下,是不是發(fā)現(xiàn)$i也隔一秒輸出一次了?這是為什么呢?
別急,我們來(lái)看看php.ini。

打開(kāi)php.ini,搜索output_buffering,我們會(huì)看到類似這樣的設(shè)置 output_buffering = 4096。正如它的名字output_buffering一樣,這個(gè)設(shè)置的作用就是把輸出緩沖一下,緩沖大小為4096bytes.

在我們的第一段代碼里,之所以沒(méi)有按預(yù)期的輸出,正是因?yàn)檫@個(gè)output_buffering把那些輸出都緩沖了。沒(méi)達(dá)到4096bytes或者腳本結(jié)束,輸出是不會(huì)被發(fā)送出去的。

而第二段代碼中的ob_end_clean()和ob_end_flush()的作用,就是終止緩沖。這樣就不用等到有4096bytes的緩沖之后才被發(fā)送出去了。

第三段代碼中,用了一句ob_flush(),它的作用就是把緩沖的數(shù)據(jù)發(fā)送出去,但是并不會(huì)終止緩沖,所以它必須在每次flush()前使用。

如果不想使用ob_end_clean(),ob_end_flush()和ob_flush(),我們就必須把php.ini里的output_buffering設(shè)得足夠小,例如設(shè)為0。需要注意的是,如果你打算在腳本中使用ini_set("output_buffering","0″)來(lái)設(shè)置,那么請(qǐng)停下來(lái)吧,這種方法是不行的。因?yàn)樵谀_本一開(kāi)始的時(shí)候,緩沖設(shè)置就已經(jīng)被載入,然后緩沖就開(kāi)始了。

可能你會(huì)問(wèn)了,既然ob_flush()是把緩沖的數(shù)據(jù)發(fā)送出去,那么為什么還需要用flush()???直接用下面這段代碼不行嗎??

<?php
for ($i=10; $i>0; $i--)
{
  echo $i;
  ob_flush();
  sleep(1);
}
?>

請(qǐng)注意ob_flush()和flush()的區(qū)別。前者是把數(shù)據(jù)從PHP的緩沖中釋放出來(lái),后者是把不在緩沖中的或者說(shuō)是被釋放出來(lái)的數(shù)據(jù)發(fā)送到瀏覽器。所以當(dāng)緩沖存在的時(shí)候,我們必須ob_flush()和flush()同時(shí)使用。

那是不是flush()在這里就是不可缺少的呢?不是的,我們還有另外一種方法,使得當(dāng)有數(shù)據(jù)輸出的時(shí)候,馬上被發(fā)送到瀏覽器。下面這兩段代碼就是不需要使用flush()了。(當(dāng)你把output_buffering設(shè)為0的時(shí)候,連ob_flush()和ob_end_clean()都不需要了)

<?php
ob_implicit_flush(true);
for ($i=10; $i>0; $i--)
{
  echo $i;
  ob_flush(); #如果ob函數(shù)打開(kāi)的情況下
  sleep(1);
}
?>
<?php
ob_end_clean();
ob_implicit_flush(true);
for ($i=10; $i>0; $i--)
{
  echo $i;
  sleep(1);
}
?>

請(qǐng)注意看上面的ob_implicit_flush(true),這個(gè)函數(shù)強(qiáng)制每當(dāng)有輸出的時(shí)候,即刻把輸出發(fā)送到瀏覽器。這樣就不需要每次輸出(echo)后,都用flush()來(lái)發(fā)送到瀏覽器了。

以上所訴可能在某些瀏覽器中不成立。因?yàn)闉g覽器也有自己的規(guī)則。我是用Firefox1.5,IE6,opera8.5來(lái)測(cè)試的。其中opera就不能正常輸出,因?yàn)樗幸粋€(gè)規(guī)則,就是不遇到一個(gè)HTML標(biāo)簽,就絕對(duì)不輸出,除非到腳本結(jié)束。而FireFox和IE還算比較正常的。

最后附上一段非常有趣的代碼,作者為PuTTYshell。在一個(gè)腳本周期里,每次輸出,都會(huì)把前一次的輸出覆蓋掉。
以下代碼只在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";
?>

看完上述內(nèi)容,你們掌握PHP中如何使用緩沖區(qū)的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI