php緩沖區輸出
1. 如何解決php無法修改header信息問題
第一種方法很簡單!就是盡量避免在肆者header和setcookie之前有任何的輸出內容。盡量將他們寫在前面。
第二種解決辦法就是利用PHP的outbuffer 輸出緩沖,旅滑PHP的輸出緩沖是這樣的 ,將當前腳本的所有輸出內容都放到outbuffer裡面,當程序執行完畢之後 將header和outbuffer一並發送給客戶端。
有兩種做裂鎮薯法 一種是在PHP.ini中開啟outbuffer output_buffering默認值為0 可以設置為Off或者On 如果要限制輸出緩沖區的最大值,可將該選項設定為指定的最大位元組數(例如 output_buffering=4096)。
另一種PHP無法修改header信息方法是在PHP腳本中做開啟:
在程序的開始出或者公共文件開始處 調用函數ob_start();
這樣我們就開啟了PHP的輸出緩沖
2. php 創建畫布為什麼要 清空(擦掉)輸出緩沖區!沒清空就不顯示創建的畫布,而是一堆亂碼!
沒有吧,一般不需要清空緩沖區,除非你在header命令前有輸出時,要清空下。
3. PHP問題求大神解答
php緩沖區,一般默認是開啟的,大小為4096比特,也就是4k左右,整個流程來說,是php緩沖區->apache緩沖區- >瀏覽器緩沖區。
1 當緩沖區滿的時候,會自動將緩沖區裡面的內容往下一級緩沖區輸送
2 當php程序運行結束的時候,緩沖區內容也會自動清空並輸出
3人為使用ob_flush將php緩沖區內容輸送到Apache緩沖區,使用flush將Apache緩沖區內容輸送到瀏覽器緩沖區
!使用ini_set是無法修改buffer的設置。
4. PHP執行循環語句時,是執行一次循環就輸出一次嗎,還是都執行完了之後一起輸出到瀏覽器
當然是一起執行完了之後再響應給瀏覽器。響應給瀏覽器的時候代表本茄橡次請求已經結束
他的順序是 :
客戶端先向服務端發送請求 -> 服務端處理請運磨求(你的循環) -> 處理完成後響應客戶端 -> 渲染給用戶旁納斗
5. 求教php 緩沖區問題
首先你找到php 的配置文件php.ini
1.php.ini中的output_buffering配置
Off: 表示關閉PHP輸出緩存
On: 打開無限大的輸出緩存
4096: 打開大小為4096Byte的輸出緩存
2.php.ini中的implicit_flush配置
On: 表示每次輸出(如echo,print)後自動調用flush()函數後,直接輸出
Off: 與On相反,每次輸出後不會調用flush(),需要等到server buffering滿了才會輸出,但是我們可以用flush()函數代替它,不開啟也沒關系,反而更加靈活
3.ob_flush()函數: 取出PHP buffering中的數據,放入server buffering
4.flush()函數: 取出Server buffering的數據,放入browser buffering
5.ob_start()函數:對於這個函數我現在了解的不是很清楚,因為開啟後輸出就會不受ob_flush()控制,即使使用ob_flush()和flush(),數據也不能立即輸出在瀏覽器上.現在知道的是,如果output_buffering=Off,即使使用了ob_start(),也是無法將輸出數據緩存的,而如果output_buffering=On的話,即使不用ob_start(),輸出數據也可以被PHP緩存,所以覺得ob_start比較廢,暫時不管他
然後我們來看代碼吧(設置output_buffering=4096,implicit_flush=Off)
最後的列印效果是
每隔一秒輸出一個
<html>
<body>
<?php
// ob_start(); //這玩意開了就會不正常,輸出不受ob_flush()控制,不知道到底幹嘛用
// echo str_repeat(' ' ,1000); //IE緩存256Bytes
echo str_repeat(' ' ,1000); //Chrome和FF緩存1000Bytes,這里用來先將瀏覽器緩存用掉,但是很疑惑這一行輸出為什麼沒有被output_buffering存起來,而是直接輸出了
for($i=0;$i<5;$i++) {
echo $i.'<br />';
ob_flush();
flush();
sleep(1);
}
?>
</body>
</html>
至於你的可以這么寫
<?php
echo str_repeat(' ' ,1000);
echo 'a<br/>';
ob_flush();
flush();
sleep(3);
echo 'b<br/>';
?>
6. php函數可以沒有輸入和輸出
1、PHP是怎麼進行輸入輸出的
php://stdin, php://stdout 和 php://stderrphp://stdin,php://stdout 和 php://stderr允許訪問 PHP 進程相應的輸入或者輸出流。php://inputphp://input 是個可以訪問請求的原始數據的只讀流。 POST 請求的情況下,最好使用 php://input 來代替 $HTTP_RAW_POST_DATA(原生的post數據),因為它不依賴於特定的 php.ini 指令,內存消耗更少。如下例:結果:php://outputphp://output 是一個只寫的數據流, 允許你以 print 和 echo 一樣的方式 寫入到輸出緩沖區。php://fdphp://fd 允許直接訪問指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。php://memory 和 php://tempphp://memory 和 php://temp 是一個類似文件 包裝器的數據流,允許讀寫臨時數據。 兩者的唯一區別是 php://memory 總是把數據儲存在內存中, 而 php://temp 會在內存量達到預定義的限制後(默認是 2MB)存入臨時文件中。
臨時文件位置的決定和 sys_get_temp_dir() 的方式一致。php://filterphp://filter 是一種元封裝器, 設計用於數據流打開時的篩選過濾應用。 這對於一體式(all-in-one)的文件函數非常有用,類似 readfile()、 file() 和 file_get_contents(), 在數據流內容讀取之前沒有機會應用其他過濾器。參數如下:如下例:
2、php用 if語句如何輸出資料庫內容
/*這里有個小錯誤:limit是確定從資料庫中讀取記錄的個數,為提高效率,一般不建議這么寫sql語句,因為你目前無法確定游標的位置,它可以在第一條記錄上,也可能在最後一條記錄上,更可能在記錄列表的任意位置
當然我理解你的用意,你是為了測試對資料庫的讀取操作,意思是只要隨意讀扮世取一條記錄就行了
但長期這么下去,你會養成一種不良的習慣,代碼不按標准去寫,也就不可能見到你想要的結果
正確的寫法是:limit[start,lenth] 例如:limit 0,1 意思是讀取第一條記錄
start代表起始位置,lenth代表讀取記錄個數(或者叫步長)就是讀取一次記錄下一次將要移動的指針位置
同時,強烈建議結合where子條件加以判斷後進行讀取。
*/if (mysql_num_rows($rs)>0){echo $rs["name"];//這里是一個致命錯誤,你是輸出不了任何數據的,因為當代碼運行到這時原時候//$rs僅僅戚核是一個mysql_query的操作句柄,更不是一個結果數組
//你用$rs["name"]去引用輸出一個不存在的數組對象高缺掘,會導致php解釋錯誤
}?>
下面是正確的寫法:
0){$row=mysql_fetch_array($rs);
echo $row["name"];}?>
7. 實時生成並下載大數據量的EXCEL文件,用PHP如何實現
對於任何一個網站肯定是少不了下載功能,常見的下載功能有圖片、視頻、Excel表格,如果文件比較小的話,那麼不會遇到任何的問題,但是當文件信息而超明銀過了PHP的最大內存,那麼在這個時候它就會有的內存溢出的問題。
那麼它們是因為什麼而發生的?對於這個過程的原理才是埋碧我們應該真正要去弄明白的事情
下載大數據量的EXCEL文件為何要報錯?
PHP在下載大Excel表格的時候,那麼首先它是需要去把MySQL的數據從硬碟上面讀取到內存,但讀取它是一次性載入到我們的內存,如果說它一次性載入的數據量遠遠大於最大內存,然後再來執行瀏覽器的業務下載。那麼這個時候它就會發生我們這個內存溢出。
就比如:說我們現在有100M的數據量,但是我們PHP內存最大隻有64M,那麼這個它肯定是裝不了的,我們可以把那個內存比喻為一個水杯,這個水杯的容量比喻為內存,現在杯子最大容量為64L。你要存放100L。肯定放不下
大事化小,小事化了。拆分成段
從上面可以看到文件下載,它是分為兩步,首先是載入內存然後執行瀏覽器的輸出下載,那麼既然大型文件一次性載入不了,那可以採用「大事化小,小事化了」思路,我們可以實現邊寫邊下載,也激液宴就是分批次的讀取與寫入。
因為用戶的話,只要最終拿到這個文件就可以,對於瀏覽器的下載原理不需要關心。只需要給到文件下載提示給用戶即可,然後後端在實時的分批次的寫入到要下載的文件當中。
實現思路步驟:
1、一設置瀏覽器下載Excel需要的Header
2、打開php://output流,並設置寫入文件句柄。
註:(php://output,是一個可寫的輸出流,允許程序像操作文件一樣將輸出寫入到輸出流中,PHP會把輸出流中的內容發送給web伺服器並返回給發起請求的瀏覽器)
3、獲取資料庫所有數據量,並設置每次查詢的條數,通過這兩個值計算分批查詢的次數
4、基於分批查詢的次數循環查詢資料庫,然後寫入到文件中,同時清除本次操作變數內存,刷新緩沖到瀏覽器,讓瀏覽器的文件始終實時保持到最新的大小
註:刷新用ob_flush、flush()PHP的I/O流
在這里我們用到了PHP的一個IO的輸入輸出,也就是我們常用的
php://inputphp://output。php://input
php://input可以讀取原始的POST數據。相較於$form-data」.
註:p>php://output是一個只寫的數據流,允許你以print和echo一樣的方式寫入到輸出緩沖區。
綜上:實現思維與原理很重要如有感悟,歡迎在線咨詢
8. 用php語言從伺服器返回數據超過80k後速度就非常非常慢!測試後發現好像是輸出緩存問題,請問怎麼解決!
對於php的輸出,貌似apache採取的策略是小段輸出直接傳輸,大段輸出就切割成chunked分段。在chunked分段沒有傳輸完成之前,apache和php一直保持連接狀態。也就是說,如果php的輸出字元串比較小,那麼apache會把這些數據暫存,等到php執行完了之後再發給瀏覽器。而當php輸出大段字元的時候,apache就不會緩存輸出,直接把輸出丟給瀏覽器,而且在此過程中會暫時停止php的執行!
所以使用緩存是解決此類問題的根本辦法。ob_start()就是啟用php的緩沖區。php還可以通過安裝xcache等緩存模塊實現。apache中開啟gzip壓縮也可以。
9. php 獲得當前文件輸出流
首先你要了解幾個php函數,下面我列出來
ob_start()函數:打開輸出緩沖區.
函數格式 void ob_start(void)
說明:當緩沖區激活時,所有來自PHP程序的非文件頭信息均不會發送,而是保存在內部緩沖區。為了輸出緩沖區的內容,可以使用ob_end_flush()或flush()輸出緩沖區的內容。
Flush:刷新緩沖區的內容,輸出。
函數格式:flush()
說明:這個函數經常使用,效率很高。
ob_get_contents :返回內部緩沖區的內容。
函數格式:string ob_get_contents(void)
說明:這個函數會返回當前緩沖區中的內容,如果輸出緩沖區沒有激活,則返回 FALSE.
ob_get_length:返回內部緩沖區的長度。
函數格式:int ob_get_length(void)
說明:這個函數會返回當前緩沖區中的長度;和ob_get_contents一樣,如果輸出緩沖區沒有激活,則返回 FALSE.
ob_end_clean:刪除內部緩沖區的內容,並且關閉內部緩沖區
函數格式:void ob_end_clean(void)
說明:這個函數不會輸出內部緩沖區的內容而是把它刪除
ob_end_flush:發送內部緩沖區的內容到瀏覽器,並且關閉輸出緩沖區
函數格式:void ob_end_flush(void)
說明:這個函數發送輸出緩沖區的內容(如果有的話)
ob_implicit_flush:打開或關閉絕對刷新
函數格式:void ob_implicit_flush ([int flag])
說明:默認為關閉緩沖區,打開絕對輸出後,每個腳本輸出都直接發送到瀏覽器,不再需要調用 flush()
是的,正如你看到的,就是利用php緩沖區,當你用ob_start()打開緩沖區的話,則你接下來的輸出,在不會輸出到瀏覽器,而是被緩存到內存上,知道內存被通知輸出獲取處理是,才會有所行動,這樣的話,你完全可以
10. php echo 形式輸出的圖片怎樣讓瀏覽器緩存(緩存相關的http頭已經試過了,無效,每次都是200),謝謝
Output Control 函數可以讓你自由控制腳本中數據的輸出。它非常地有用,特別是對於:當你想在數據已經輸出後,再輸出文件頭的情況。
輸出控制函數不對使用 header() 或 setcookie(), 發送的文件頭信息產生影響,只對那些類似於 echo() 和 PHP 代碼的數據塊有作用。
我們先舉一個簡單的例子,讓大家對Output Control有一個大致的印象:
Example 1.
復制代碼 代碼如下:
<?php
ob_start(); //打開緩沖區
echo \"Hellon\"; //輸出
header(「location:index.php」); //把瀏覽器重定向到index.php
ob_end_flush();//輸出全部內容到瀏覽器
?>
所有對header()函數有了解的人都知道,這個函數會發送一段文件頭給瀏覽器,但是如果在使用這個函數之前已經有了任何輸出(包括空輸出,比如空格,回車和換行)就會提示出錯。如果我們去掉第一行的ob_start(),再執行此程序,我們會發現得到了一條錯誤提示:「Header had all ready send by」!但是加上ob_start,就不會提示出錯,原因是當打開了緩沖區,echo後面的字元不會輸出到瀏覽器,而是保留在伺服器,直到你使用 flush或者ob_end_flush才會輸出,所以並不會有任何文件頭輸出的錯誤!
一、 相關函數簡介:
1、Flush:刷新緩沖區的內容,輸出。
函數格式:flush()
說明:這個函數經常使用,效率很高。
2、ob_start :打開輸出緩沖區
函數格式:void ob_start(void)
說明:當緩沖區激活時,所有來自PHP程序的非文件頭信息均不會發送,而是保存在內部緩沖區。為了輸出緩沖區的內容,可以使用ob_end_flush()或flush()輸出緩沖區的內容。
3 、ob_get_contents :返回內部緩沖區的內容。
使用方法:string ob_get_contents(void)
說明:這個函數會返回當前緩沖區中的內容,如果輸出緩沖區沒有激活,則返回 FALSE 。
4、ob_get_length:返回內部緩沖區的長度。
使用方法:int ob_get_length(void)
說明:這個函數會返回當前緩沖區中的長度;和ob_get_contents一樣,如果輸出緩沖區沒有激活。則返回 FALSE。
5、ob_end_flush :發送內部緩沖區的內容到瀏覽器,並且關閉輸出緩沖區。
使用方法:void ob_end_flush(void)
說明:這個函數發送輸出緩沖區的內容(如果有的話)。
6、ob_end_clean:刪除內部緩沖區的內容,並且關閉內部緩沖區
使用方法:void ob_end_clean(void)
說明:這個函數不會輸出內部緩沖區的內容而是把它刪除!
7、ob_implicit_flush:打開或關閉絕對刷新
使用方法:void ob_implicit_flush ([int flag])
說明:使用過Perl的人都知道$|=x的意義,這個字元串可以打開/關閉緩沖區,而ob_implicit_flush函數也和那個一樣,默認為關閉緩沖區,打開絕對輸出後,每個腳本輸出都直接發送到瀏覽器,不再需要調用 flush()
二、深入了解:
1. 關於Flush函數:
這個函數在PHP3中就出現了,是一個效率很高的函數,他有一個非常有用的功能就是刷新browser的cache.我們舉一個運行效果非常明顯的例子來說明flush.
Example 2.
復制代碼 代碼如下:
<?php
for($i = 1; $i <= 300; $i++ ) print(「 「);
// 這一句話非常關鍵,cache的結構使得它的內容只有達到一定的大小才能從瀏覽器里輸出
// 換言之,如果cache的內容不達到一定的大小,它是不會在程序執行完畢前輸出的。經
// 過測試,我發現這個大小的底限是256個字元長。這意味著cache以後接收的內容都會
// 源源不斷的被發送出去。
For($j = 1; $j <= 20; $j++) {
echo $j.」
」;
flush(); //這一部會使cache新增的內容被擠出去,顯示到瀏覽器上
sleep(1); //讓程序「睡」一秒鍾,會讓你把效果看得更清楚
}
?>
具體效果你可以到這里看看http://www.php2000.com/~uchinaboy/out.php
PHP2000的最新的PHP聊天室就是用的這個技術,可惜的是源代碼未公開 L
註:如果在程序的首部加入ob_implicit_flush()打開絕對刷新,就可以在程序中不再使用flush(),這樣做的好處是:提高效率!
2. 關於ob系列函數:
我想先引用我的好朋友y10k的一個例子:
Example 3.
比如你用得到伺服器和客戶端的設置信息,但是這個信息會因為客戶端的不同而不同,如果想要保存phpinfo()函數的輸出怎麼辦呢?在沒有緩沖區控制之前,可以說一點辦法也沒有,但是有了緩沖區的控制,我們可以輕松的解決:
復制代碼 代碼如下:
<?php
ob_start(); //打開緩沖區
phpinfo(); //使用phpinfo函數
$info=ob_get_contents(); //得到緩沖區的內容並且賦值給$info
$file=fopen(\'info.txt\',\'w\'); //打開文件info.txt
fwrite($file,$info); //寫入信息到info.txt
fclose($file); //關閉文件info.txt
?>
用以上的方法,就可以把不同用戶的phpinfo信息保存下來,這在以前恐怕沒有辦法辦到!其實上面就是將一些「過程」轉化為「函數」的方法!
或許有人會問:「難道就這個樣子嗎?還有沒有其他用途?」當然有了,比如筆者論壇的PHP 語法加亮顯示就和這個有關(PHP默認的語法加亮顯示函數會直接輸出,不能保存結果,如果在每次調用都顯示恐怕會很浪費CPU,筆者的論壇就把語法加亮函數顯示的結果用控制緩沖區的方法保留了),大家如果感興趣的話可以來看看http://www.zphp.com/bbs/!
可能現在大家對ob_start()的功能有了一定的了解,上面的一個例子看似簡單,但實際上已經掌握了使用ob_start()的要點。
<1>.使用ob_start打開browser的cache,這樣可以保證cache的內容在你調用flush(),ob_end_flush()(或程序執行完畢)之前不會被輸出。
<2>.現在的你應該知道你所擁有的優勢:可以在任何輸出內容後面使用header,setcookie以及session,這是 ob_start一個很大的特點;也可以使用ob_start的參數,在cache被寫入後,然後自動運行命令,比如 ob_start(\"ob_gzhandler\");而我們最常用的做法是用ob_get_contents()得到cache中的內容,然後再進行處理……
<3>.當處理完畢後,我們可以使用各種方法輸出,flush(),ob_end_flush(),以及等到程序執行完畢後的自動輸出。當然,如果你用的是ob_get_contents(),那麼就要你自己控制輸出方式了。
來,讓我們看看能用ob系列函數做些什麼……
一、 靜態模版技術
簡介:所謂靜態模版技術就是通過某種方式,使得用戶在client端得到的是由PHP產生的html頁面。如果這個html頁面不會再被更新,那麼當另外的用戶再次瀏覽此頁面時,程序將不會再調用PHP以及相關的資料庫,對於某些信息量比較大的網站,例如sina,163,sohu。類似這種的技術帶來的好處是非常巨大的。
我所知道的實現靜態輸出的有兩種辦法:
<1>.通過y10k修改的phplib的一個叫template.inc.php類實現。
<2>.使用ob系列函數實現。
對於第一種方法,因為不是這篇文章所要研究的問題,所以不再贅述。
我們現在來看一看第二種方法的具體實現:
Example 4.
<?php
ob_start();//打開緩沖區
?>
php頁面的全部輸出
<?
$content = ob_get_contents();//取得php頁面輸出的全部內容
$fp = fopen(「output00001.html」, 「w」); //創建一個文件,並打開,准備寫入
fwrite($fp, $content); //把php頁面的內容全部寫入output00001.html,然後……
fclose($fp);
?>
這樣,所謂的靜態模版就很容易的被實現了……
二、 捕捉輸出
以上的Example 4.是一種最簡單的情況,你還可以在寫入前對$content進行操作……
你可以設法捕捉一些關鍵字,然後去對它進行再處理,比如Example 3.所述的PHP語法高亮顯示。個人認為,這個功能是此函數最大的精華所在,它可以解決各種各樣的問題,但需要你有足夠的想像力……
Example 5.
<?
Function run_code($code) {
If($code) {
ob_start();
eval($code);
$contents = ob_get_contents();
ob_end_clean();
}else {
echo 「錯誤!沒有輸出」;
exit();
}
return $contents;
}
以上這個例子的用途不是很大,不過很典型$code的本身就是一個含有變數的輸出頁面,而這個例子用eval把$code中的變數替換,然後對輸出結果再進行輸出捕捉,再一次的進行處理……
Example 6. 加快傳輸
<?
/*
** Title.........: PHP4 HTTP Compression Speeds up the Web
** Version.......: 1.20
** Author........: catoc <[email protected]>
** Filename......: gzdoc.php
** Last changed..: 18/10/2000
** Requirments...: PHP4 >= 4.0.1
** PHP was configured with --with-zlib[=DIR]
** Notes.........: Dynamic Content Acceleration compresses
** the data transmission data on the fly
** code by sun jin hu (catoc) <[email protected]>
** Most newer browsers since 1998/1999 have
** been equipped to support the HTTP 1.1
** standard known as \"content-encoding.\"
** Essentially the browser indicates to the
** server that it can accept \"content encoding\"
** and if the server is capable it will then
** compress the data and transmit it. The
** browser decompresses it and then renders
** the page.
**
** Modified by John Lim ([email protected])
** based on ideas by Sandy McArthur, Jr
** Usage........:
** No space before the beginning of the first \'<?\' tag.
** ------------Start of file----------
** |<?
** | include(\'gzdoc.php\');
** |? >
** |<HTML>
** |... the page ...
** |</HTML>
** |<?
** | gzdocout();
** |? >
** -------------End of file-----------
*/
ob_start();
ob_implicit_flush(0);
function CheckCanGzip(){
global $HTTP_ACCEPT_ENCODING;
if (headers_sent() || connection_timeout() || connection_aborted()){
return 0;
}
if (strpos($HTTP_ACCEPT_ENCODING, \'x-gzip\') !== false) return \"x-gzip\";
if (strpos($HTTP_ACCEPT_ENCODING,\'gzip\') !== false) return \"gzip\";
return 0;
}
/* $level = compression level 0-9, 0=none, 9=max */
function GzDocOut($level=1,$debug=0){
$ENCODING = CheckCanGzip();
if ($ENCODING){
print \"n<!-- Use compress $ENCODING -->n\";
$Contents = ob_get_contents();
ob_end_clean();
if ($debug){
$s = \"<p>Not compress length: \".strlen($Contents);
$s .= \"
Compressed length: \".strlen(gzcompress($Contents,$level));
$Contents .= $s;
}
header(\"Content-Encoding: $ENCODING\");
print \"x1fx8bx08x00x00x00x00x00\";
$Size = strlen($Contents);
$Crc = crc32($Contents);
$Contents = gzcompress($Contents,$level);
$Contents = substr($Contents, 0, strlen($Contents) - 4);
print $Contents;
print pack(\'V\',$Crc);
print pack(\'V\',$Size);
exit;
}else{
ob_end_flush();
exit;
}
}
?>
這是catoc的一段很早以前的代碼,是在weblogs.com看到的,他利用了zlib的函數,對傳輸的內容進行了壓縮,測試表明,對於10k以上的頁面,會產生效果,而且頁面越大,效果越明顯……